poj1981Circle and Points(单位圆覆盖最多的点)

链接

O(n^3)的做法:

枚举任意两点为弦的圆,然后再枚举其它点是否在圆内。

用到了两个函数

atan2反正切函数,据说可以很好的避免一些特殊情况

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<cmath>

 8 #include<queue>

 9 #include<set>

10 using namespace std;

11 #define N 310

12 #define LL long long

13 #define INF 0xfffffff

14 const double eps = 1e-8;

15 const double pi = acos(-1.0);

16 const double inf = ~0u>>2;

17 struct point

18 {

19     double x,y;

20     point(double x = 0,double y =0 ):x(x),y(y){}

21 }p[N];

22 double dis(point a,point b)

23 {

24     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

25 }

26 point getcircle(point p1,point p2)

27 {

28     point mid = point((p1.x+p2.x)/2,(p2.y+p1.y)/2);

29     double angle = atan2(p2.y-p1.y,p2.x-p1.x);

30     double d = sqrt(1.0-dis(p1,mid)*dis(p1,mid));

31     return point(mid.x+d*sin(angle),mid.y-d*cos(angle));

32 }

33 int dcmp(double x)

34 {

35     if(fabs(x)<eps)return 0;

36     else return x<0?-1:1;

37 }

38 int main()

39 {

40     int i,j,n;

41     while(scanf("%d",&n)&&n)

42     {

43         for(i = 1 ;i <= n; i++)

44         scanf("%lf%lf",&p[i].x,&p[i].y);

45         int maxz = 1;

46         for(i = 1; i <= n; i++)

47             for(j = i+1 ; j <= n ;j++)

48             {

49                 if(dis(p[i],p[j])>2.0) continue;

50                 int tmax = 0;

51                 point cir = getcircle(p[i],p[j]);

52                 for(int g =  1; g <= n ;g++)

53                 {

54                     if(dcmp(dis(cir,p[g])-1.0)>0)

55                     continue;

56                     tmax++;

57                 }

58                 maxz = max(maxz,tmax);

59             }

60         printf("%d\n",maxz);

61     }

62     return 0;

63 }
View Code

O(n^2log(n))

这个类似扫描线的做法,以每一个点为圆心化圆,枚举与其相交得圆,保存交点和角度,按角度排序后,扫一遍。

 

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<cmath>

 8 #include<queue>

 9 #include<set>

10 using namespace std;

11 #define N 310

12 #define LL long long

13 #define INF 0xfffffff

14 const double eps = 1e-8;

15 const double pi = acos(-1.0);

16 const double inf = ~0u>>2;

17 struct point

18 {

19     double x,y;

20     point(double x = 0,double y =0 ):x(x),y(y) {}

21 } p[N];

22 struct node

23 {

24     double ang;

25     int in;

26 } arc[N*N];

27 double dis(point a,point b)

28 {

29     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

30 }

31 int dcmp(double x)

32 {

33     if(fabs(x)<eps)return 0;

34     else return x<0?-1:1;

35 }

36 bool cmp(node a,node b)

37 {

38     if(dcmp(a.ang-b.ang)==0)

39         return a.in>b.in;

40     return dcmp(a.ang-b.ang)<0;

41 }

42 int main()

43 {

44     int i,j,n;

45     while(scanf("%d",&n)&&n)

46     {

47         for(i = 1 ; i <= n; i++)

48             scanf("%lf%lf",&p[i].x,&p[i].y);

49         int g = 0;

50         int ans = 0,maxz = 1;

51         for(i = 1; i <= n ; i++)

52         {

53             ans = 0;

54             g = 0;

55             for(j = 1; j <= n ; j++)

56             {

57                 if(dis(p[i],p[j])>2.0) continue;

58                 double ang1 = atan2(p[j].y-p[i].y,p[j].x-p[i].x);

59                 double ang2 = acos(dis(p[i],p[j])/2);

60                 arc[++g].ang = ang1-ang2;//这里角度的算法很巧妙

61                 arc[g].in = 1;

62                 arc[++g].ang = ang1+ang2;

63                 arc[g].in = -1;

64             }

65             sort(arc+1,arc+g+1,cmp);

66 

67             //cout<<g<<endl;

68             for(j = 1 ; j <= g;j++)

69             {

70                 ans+=arc[j].in;

71                 maxz = max(maxz,ans);

72             }

73         }

74         printf("%d\n",maxz);

75     }

76     return 0;

77 }
View Code

你可能感兴趣的:(poi)