zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",maxz);
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    最小生成树(Prim和Kruscal)
    SPFA(还是稍微写写吧,虽然没什么用)
    最短路径(随便写写)(Floyd,Bellman-Ford,Dijkstra)
    Just a Hook HDU
    数论逆元
    最长上升子序列(LIS)算法(附Codeforces Round #641 (Div. 2),B题题解)
    Educational Codeforces Round 86 (Rated for Div. 2)
    Codeforces Round #633 (Div. 2)
    Codeforces Round #631 (Div. 2)
    Mayor's posters(线段树离散化)
  • 原文地址:https://www.cnblogs.com/shangyu/p/3855353.html
Copyright © 2011-2022 走看看