POJ 1118 Lining Up(点与直线)
http://poj.org/problem?id=1118
题意: 同POJ2780 POJ2606
给你n个二维平面点的坐标,问你最多有多少个点共线?
分析:
首先我们直观的方法是找出所给点集的所有可能的直线,然后对于每条直线,看看有多少个其他的点在该直线上. 最后更新最大值即可.
程序1实现找用到了定序的技巧,保证不会丢失最优解. 比如某条直线上有5个点且是最多的.这5个点分别编号为1,4,5,7,8.那么我们用下面第2种方式来实现代码:
可以看到1肯定是i, 4肯定是j, 然后k分别遍历到了5,7,8.
暴力枚举见代码1.
下面是通过排序来降低一点复杂度的方法二.
我们枚举每一个点,把该点作为固定点,然后我们计算剩下的所有点与该点构成直线的斜率(注意处理斜率不存在的情况),把这些斜率保存在数组S中,然后对S数组排序,那么斜率相同的值就会变成连续存放.那些斜率相同的值就代表的共线的点,这样就可算出最多有多少点共线.(程序实现同样用了定序的技巧)
AC代码:
暴力枚举890ms
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=700+5; struct Point { double x,y; Point(){} Point(double x,double y):x(x),y(y){} }p[maxn]; typedef Point Vector; Vector operator-(Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); } double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } bool In_Line(Point A,Point B,Point C)//判断3点共线 { return fabs(Cross(A-B,A-C))<1e-10; } int main() { int n; while(scanf("%d",&n)==1 && n) { for(int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y); int ans=2; for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) { int sum=2; for(int k=j+1;k<=n;++k) if(In_Line(p[i],p[j],p[k])) ++sum; ans=max(ans,sum); } printf("%d\n",ans); } return 0; }
排序优化125ms
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn=700+5; const double eps=1e-10; const double INF=1e20; int dcmp(double x) { if(fabs(x)<eps) return 0; return x<0?-1:1; } struct Point { double x,y; Point(){} Point(double x,double y):x(x),y(y){} }p[maxn]; double get_slope(Point A,Point B) { if(A.x==B.x) return INF; else return (A.y-B.y)/(A.x-B.x); } int main() { int n; while(scanf("%d",&n)==1 && n) { for(int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y); int ans=2; for(int i=1;i<=n;++i) { int num=0;//保存斜率 double S[maxn];//保存斜率 for(int j=i+1;j<=n;++j) S[num++]=get_slope(p[i],p[j]); sort(S,S+num); int sum=1;//计数相同斜率点的个数 for(int j=1;j<num;++j) { if(S[j]==S[j-1]) ++sum;//相同斜率点数加1 else { ans=max(ans,sum+1);//+1是加上枚举的i端点 sum=1; } } ans=max(ans,sum+1);//这句不加,无限WA哦 } printf("%d\n",ans); } }