题意:
给n个点,判断其中最多有多少个点共线。
分析:
n<=1000,n^3的算法会TLE。将所有点按y从小到大排序,若y相同按x排序,这样每次确定跟点i最多有多少点共线就只需看要下标比i大的点了。对于每个点i,将下标比i大的点按与i成的角度排序,这样所有与i共线的点必然在新排序中相邻,遍历一遍取最大值就可以了。n^2*logn的复杂度。
代码:
//poj 3512
//sepNINE
#include<iostream>
#include<algorithm>
using namespace std;
char tmp[1024];
int n,cases,end;struct Point
{__int64 x,y;
}p[1024],np[1024];
int cmp(Point a,Point b)
{if(a.y!=b.y)return a.y<b.y;return a.x<b.x;
}int cmp1(Point a,Point b)
{if(a.x*b.y==a.y*b.x)return 1;return a.x*b.y>a.y*b.x;
}void solve()
{if(n==1){printf("%d. %d\n",++cases,1);return ;}int ans=2;int i,j,k;sort(p,p+n,cmp);for(i=0;i<n;++i){int num,cnt;num=1;cnt=0;for(j=i+1;j<n;++j){np[num].x=p[j].x-p[i].x;np[num].y=p[j].y-p[i].y;++num;}np[0].x=0,np[0].y=0;if(num<3)continue;sort(np+1,np+num,cmp1); for(j=1;j<num;++j)if(np[j].x*np[j-1].y==np[j].y*np[j-1].x)++cnt;else{ans=max(ans,cnt+1);cnt=1;}ans=max(ans,cnt+1);}printf("%d. %d\n",++cases,ans);
}int main()
{end=n=cases=0;while(1){gets(tmp); if(tmp[0]=='-'&&tmp[1]=='-'){if(n>0)solve();n=0;++end;if(end==2)break;}else{sscanf(tmp,"%I64d%I64d",&p[n].x,&p[n].y);end=0;++n;} }return 0;
}