题目大意:给N个二维点的坐标,求在所有点的连线中一条直线所能包含最多的点的个数;2000ms,1000的复杂度
刚开始自己想了个N^3复杂度的方法,即使加上了感觉很有效的剪枝,但是依然TLE了。看了网上某ACMer的博客,恍然大悟,原来N^2logN就可以过了;
大致思路:枚举每一个点:计算其他所有点和此点连线的斜率,然后将斜率排序。此时,便可以在排好序的斜率中将相等的斜率数量找出来(斜率相等则说明在同一条直线上)。
枚举每个点复杂度N,每次排序NlogN.所以总复杂度为N^2logN。以下是实现的代码:
#include <stdio.h>
#include <math.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#define inf 0x6FFFFFFF
using namespace std;
struct point
{
int x,y;
};
vector<point> points ;
double getslope(point a,point b)
{
if(a.x!=b.x)
return double(a.y-b.y)/double(a.x-b.x);
return inf;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
points.clear();
int m;
scanf("%d",&m);
for(int j=0; j<m; j++)
{
point a;
scanf("%d%d",&a.x,&a.y);
points.push_back(a);
}
int ma=0;
if(m<=2)
ma=m;
else
{
for(int j=0; j<points.size(); j++)
{
vector<double> vec;
vec.clear();
for(int k=0; k<points.size(); k++)
{
if(k==j)
continue;
vec.push_back(getslope(points[j],points[k]));
// cout<<getslope(points[j],points[k])<<endl;
}
sort(vec.begin(),vec.end());
int sum=1;
double e=-inf;
for(int h=0; h<vec.size(); h++)
{
if(vec[h]==e)
sum++;
else
{
e=vec[h];
ma=max(ma,sum);
// cout<<ma<<" "<<e<<endl;
sum=2;
}
}
ma=max(ma,sum);
}
}
printf("Case %d: %d\n",i,ma);
}
return 0;
}