题意 : 给你很多点和一个半径r,这个半径为r的圆能覆盖的最多的点是多少。
思路 : 对每个点做半径为 r 的圆, 求交集,交集最多的区域的被覆盖次数就是能覆盖的最多的点。贴两个链接,分析的挺好,代码写得挺好
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <iostream> 5 #include <algorithm> 6 7 using namespace std ; 8 9 const double eps = 1e-8 ; 10 const double PI = acos(-1.0) ; 11 int n ; 12 double r ; 13 14 struct point 15 { 16 double x,y ; 17 }p[2010] ; 18 struct node 19 { 20 double angle ; 21 int flag ; 22 }q[4030] ; 23 24 inline int dcmp(double d) 25 { 26 return d < -eps ? -1 : d > eps ; 27 } 28 bool cmp(const node &a,const node &b)//角度区间排序 29 { 30 if(dcmp(a.angle-b.angle) == 0 ) return a.flag > b.flag ; 31 return a.angle < b.angle ; 32 } 33 double Sqrt(double x) 34 { 35 return x*x ; 36 } 37 double dist(const point &a,const point &b) 38 { 39 return sqrt(Sqrt(a.x-b.x)+Sqrt(a.y-b.y)) ; 40 } 41 42 int main() 43 { 44 while(~scanf("%d %lf",&n,&r)) 45 { 46 if(n == 0) break ; 47 for(int i = 0 ; i < n ; i++) 48 scanf("%lf %lf",&p[i].x,&p[i].y) ; 49 int ans = 0 ; 50 for(int i = 0 ; i < n ; i++) 51 { 52 int m = 0 ; 53 for(int j = 0 ; j < n ; j++) 54 { 55 if(i == j) continue ; 56 double d = dist(p[i],p[j]) ; 57 if(d > 2*r+0.001) continue ; 58 double s = atan2(p[j].y-p[i].y,p[j].x-p[i].x) ; 59 if(s < 0) s += 2*PI ;//角度区间修正 60 double ph = acos(d/2.0/r) ;//圆心角转区间 61 q[m++].angle = s - ph + 2*PI ;q[m-1].flag = 1 ; 62 q[m++].angle = s + ph + 2*PI ;q[m-1].flag = -1 ; 63 } 64 sort(q,q+m,cmp) ; 65 int sum = 0 ; 66 for(int j = 0 ; j < m ; j++) 67 ans = max(ans,sum += q[j].flag) ; 68 } 69 printf("It is possible to cover %d points. ",ans+1) ; 70 } 71 return 0 ; 72 }