题意:
给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;
}