1118 Lining Up
問題概要
座標平面上の点がn個与えられる。
一直線上に乗る最大の点の数を求めよ。
n<700,点の座標は全て整数とする。
解法
点iを決める。
点iと点jを結んだ傾きと点i点kを結んだ傾きが一致すれば、三点i,j,kは同一直線上にある。
したがって点iから、傾きαを作る点の数をcnt[α]などと連想配列にして数えれば、
その最大値が点iから引いた直線が、同時に乗せる点の最大数である。
これを全てのiについて動かす。
また、STLのmapを使うと遅くてダメなので、適当にハッシュなどを作る。
ソースコード
const int sz=2003; int v[sz]; pair<int,int> ky[sz]; void hClr(){ rep(i,sz)ky[i]=mp(-1,-1),v[i]=0; } int inc(pair<int,int> key){ int h=(key.first*29+key.second)%sz; if(h<0)h+=sz; for(;ky[h]!=mp(-1,-1);h=(h+1)%sz)if(ky[h]==key)break; ky[h]=key; return ++v[h]; } int main(){ int n,x[700],y[700]; while(scanf("%d",&n),n){ rep(i,n)scanf("%d%d",x+i,y+i); int ans=min(n,2); rep(i,n){ hClr(); int mx=0; rep(j,n)if(i!=j){ int dx=x[j]-x[i],dy=y[j]-y[i],g=dx&&dy?__gcd(dx,dy):dx+dy; dx/=g; dy/=g; if(dx<0)dx*=-1,dy*=-1; mx=max(mx,inc(mp(dx,dy))); } ans=max(ans,mx+1); } printf("%d\n",ans); } return 0; }