题目连接:http://zuojie.3322.org:88/soj/problem.action?id=4021
题目:
Description
You probably know what a set of collinear points is: a set of points such that there exists astraight line that passes through all of them. A set of cocircular points is defined in the samefashion, but instead of a straight line, we ask that there is a circle such that every point of theset lies over its perimeter.The International Collinear Points Centre (ICPC) has assigned you the following task: given aset of points, calculate the size of the larger subset of cocircular points.
Input
Each test case is given using several lines. The first line contains an integer N representing thenumber of points in the set (1 <= N <= 100). Each of the next N lines contains two integers Xand Y representing the coordinates of a point of the set (-10^4 <= X, Y <= 10^4). Within eachtest case, no two points have the same location.The last test case is followed by a line containing one zero.
Output
For each test case output a single line with a single integer representing the number of pointsin one of the largest subsets of the input that are cocircular.
Sample Input
7-10 00 -1010 00 10-20 10-10 20-2 44-10000 1000010000 1000010000 -10000-10000 -99993-1 00 01 00
Sample Output
532<!-->SourceLatin American Regional Contest 2010--></!-->
直接枚举三个点,然后去计算圆心的方法是会超时的,标准的方法是去枚举两个点,然后在枚举第三个点,看构成的圆的圆心有多少重复再了一个地方。
通过统计这些次数我们便可以知道最多有多少个点共圆。
时间复杂度也就可以从O(n^4)降到了O(n^3logn)
虽然还是很高,但是适当的剪枝(比如枚举的时候只需要枚举一半左右的点)
还是可以过的。
我的代码:
#include<stdio.h> #include<algorithm> #include<math.h> #define eps 1e-8 using namespace std; struct node { double x; double y; }; struct line { node a; node b; }; node p[105]; int n; bool cmp(node a,node b) { if((a.x<b.x)||((fabs(a.x-b.x)<=eps)&&(a.y<b.y))) return true; return false; } double xmult(node p1,node p2,node p0) { return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } bool judge_line(int a,int b,int c) { double temp; temp=xmult(p[a],p[b],p[c]); if(fabs(temp)<=eps) return false; else return true; } node circle(node p1,node p2,node p3) { node p; double a1=2*(p1.x-p2.x); double a2=2*(p1.x-p3.x); double b1=2*(p1.y-p2.y); double b2=2*(p1.y-p3.y); double c1=p1.x*p1.x+p1.y*p1.y-p2.x*p2.x-p2.y*p2.y; double c2=p1.x*p1.x+p1.y*p1.y-p3.x*p3.x-p3.y*p3.y; double t=a1*b2-a2*b1; p.x=(c1*b2-c2*b1)/t; p.y=(a1*c2-a2*c1)/t; return p; } int getans(int a,int b) { int i,num=0,kkk=3,ret=0; double dis; node center[105]; for(i=b+1;i<=n;i++) { if(judge_line(i,a,b)) center[num++]=circle(p[a],p[b],p[i]); } if(num==0) return 2; sort(center,center+num,cmp); for(i=1;i<num;i++) { dis=(center[i-1].x-center[i].x)*(center[i-1].x-center[i].x)+(center[i-1].y-center[i].y)*(center[i-1].y-center[i].y); if(dis<=eps) kkk++; else { if(kkk>ret) ret=kkk; kkk=3; } } if(kkk>ret) ret=kkk; return ret; } int main() { int i,j,temp,max; while(scanf("%d",&n)!=EOF) { if(n==0) break; max=0; for(i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) { temp=getans(i,j); if(temp>max) max=temp; } printf("%d\n",max); } return 0; }