POJ 1981 定长圆覆盖最多点

题意:

一些点,求一个单位圆最多能覆盖的点的个数,不存在两点距离恰好为2.

 

题解:

暴力枚举两个点,求圆心,然后枚举每个点验证是否在圆内。n^3的,可以过~

当然还有n^2logn的转化为求圆的最大弧的覆盖次数问题(以后做CIRU 的时候也会用到这个技术~)

 

n^3

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <cmath>
  7 
  8 #define N 333
  9 #define EPS 1e-7
 10 #define PI 3.141592653589793238
 11 #define INF 1e10
 12 
 13 using namespace std;
 14 
 15 struct PO
 16 {
 17     double x,y;
 18     void prt() {printf("%lf      %lf\n",x,y);}
 19 }p[N];
 20 
 21 int n,ans;
 22 
 23 const double r=1.0;
 24 
 25 inline void read()
 26 {
 27     for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
 28 }
 29 
 30 inline PO operator +(PO a,PO b)
 31 {
 32     PO c;
 33     c.x=a.x+b.x; c.y=a.y+b.y;
 34     return c;
 35 }
 36 
 37 inline PO operator -(PO a,PO b)
 38 {
 39     PO c;
 40     c.x=a.x-b.x; c.y=a.y-b.y;
 41     return c;
 42 }
 43 
 44 inline int dc(double x)
 45 {
 46     if(x>EPS) return 1;
 47     else if(x<-EPS) return -1;
 48     return 0;
 49 }
 50 
 51 inline double getdis2(PO &a,PO &b)
 52 {
 53     return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
 54 }
 55 
 56 inline double getlen(PO &a)
 57 {
 58     return sqrt(a.x*a.x+a.y*a.y);
 59 }
 60 
 61 inline PO rotate(PO a)
 62 {
 63     PO ans;
 64     ans.x=a.y;
 65     ans.y=-a.x;
 66     return ans;
 67 }
 68 
 69 inline PO geto(PO &a,PO &b)
 70 {
 71     PO mid=a+b;
 72     mid.x/=2; mid.y/=2;
 73     PO ab=b-a;
 74     double len=getlen(ab);
 75     ab.x/=len; ab.y/=len;
 76     ab=rotate(ab);
 77     len=sqrt(r-len*len*0.25);
 78     ab.x*=len; ab.y*=len;
 79     return mid+ab;
 80 }
 81 
 82 inline void check(PO &o)
 83 {
 84     int res=0;
 85     for(int i=1;i<=n;i++)
 86         if(dc(getdis2(p[i],o)-r)<=0) res++;
 87     ans=max(res,ans);
 88 }
 89 
 90 inline void go()
 91 {
 92     ans=1;PO o;
 93     for(int i=1;i<=n;i++)
 94         for(int j=i+1;j<=n;j++)
 95             if(dc(getdis2(p[i],p[j])-4*r)<=0)
 96             {
 97                 o=geto(p[i],p[j]);
 98                 check(o);
 99                 o=geto(p[j],p[i]);
100                 check(o);
101             }
102     printf("%d\n",ans);
103 }
104 
105 int main()
106 {
107     while(scanf("%d",&n),n) read(),go();
108     return 0;
109 }

 

 

n^2logn

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <algorithm>
  7 
  8 #define N 777
  9 #define PI 3.141592653589
 10 #define EPS 1e-7
 11 
 12 using namespace std;
 13 //定长圆覆盖最多点,转为最大弧覆盖次数 
 14 struct C
 15 {
 16     double x,y,r;
 17     void prt() {printf("%lf      %lf\n",x,y);}
 18 }c[N];
 19 
 20 struct T
 21 {
 22     int fg;
 23     double ag;
 24     void prt() {printf("%lf     %d\n",ag,fg);}
 25 }t[N<<2];
 26 
 27 int n,cnt,ans;
 28 double ccd,r=1.0;
 29 
 30 inline int dc(double x)
 31 {
 32     if(x>EPS) return 1;
 33     else if(x<-EPS) return -1;
 34     return 0;
 35 }
 36 
 37 inline C operator +(C a,C b)
 38 {
 39     C tmp;
 40     tmp.x=a.x+b.x; tmp.y=a.y+b.y;
 41     return tmp;
 42 }
 43 
 44 inline C operator -(C a,C b)
 45 {
 46     C tmp;
 47     tmp.x=a.x-b.x; tmp.y=a.y-b.y;
 48     return tmp;
 49 }
 50 
 51 inline C operator *(C a,double k)
 52 {
 53     a.x*=k; a.y*=k;
 54     return a;
 55 }
 56 
 57 inline C operator /(C a,double k)
 58 {
 59     a.x/=k; a.y/=k;
 60     return a;
 61 } 
 62 
 63 inline void read()
 64 {
 65     for(int i=1;i<=n;i++)
 66     {
 67         scanf("%lf%lf",&c[i].x,&c[i].y);
 68         c[i].r=1.0;
 69     }
 70 }
 71 
 72 inline bool cmp(const T &a,const T &b)
 73 {
 74     if(dc(a.ag-b.ag)==0) return a.fg>b.fg;
 75     return a.ag<b.ag;
 76 }
 77 
 78 inline double getdis(const C &a,const C &b)
 79 {
 80     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 81 }
 82 
 83 inline C getf(const C &a,const C &b)//单位法向量 
 84 {
 85     C tmp=b-a; tmp=tmp/ccd;
 86     C ans;
 87     ans.x=-tmp.y; ans.y=tmp.x;
 88     return ans;
 89 }
 90 
 91 inline void getcpoint(const C &c1,const C c2,C &a,C &b)
 92 {
 93     double cs=(c2.r*c2.r+ccd*ccd-c1.r*c1.r)/(2*ccd);
 94     double cp=ccd-cs;
 95     double hh=sqrt(c1.r*c1.r-cp*cp);
 96     C f=getf(c1,c2);
 97     f=f*hh;
 98     a=((c2-c1)*cp/ccd-f);
 99     b=((c2-c1)*cp/ccd+f);
100 }
101 
102 inline void go()
103 {
104     ans=0;
105     C o1,o2;
106     for(int i=1;i<=n;i++)
107     {
108         cnt=0;
109         for(int j=1;j<=n;j++)
110         {
111             if(i==j) continue;
112             ccd=getdis(c[i],c[j]);
113             if(dc(ccd-2*r)>0) continue;
114             getcpoint(c[i],c[j],o1,o2);
115             double ag1=atan2(o1.y,o1.x);
116             double ag2=atan2(o2.y,o2.x);
117             if(dc(ag1)>0&&dc(ag2)<=0)//跨越x轴负半轴,拆开 
118             {
119                 t[++cnt].fg=1; t[cnt].ag=ag1;
120                 t[++cnt].fg=-1; t[cnt].ag=PI;
121                 t[++cnt].fg=1; t[cnt].ag=-PI;
122                 t[++cnt].fg=-1; t[cnt].ag=ag2;
123             }
124             else 
125             {
126                 t[++cnt].fg=1; t[cnt].ag=ag1;
127                 t[++cnt].fg=-1; t[cnt].ag=ag2;
128             }
129         }
130         sort(t+1,t+1+cnt,cmp);
131         int res=0;
132         for(int j=1;j<=cnt;j++)
133         {
134             res+=t[j].fg;
135             ans=max(ans,res);
136         }
137     }
138     printf("%d\n",ans+1);
139 }
140 
141 int main()
142 {
143     while(scanf("%d",&n),n) read(),go();
144     return 0;
145 }

 

 

 

 

转载于:https://www.cnblogs.com/proverbs/archive/2013/02/28/2937950.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值