POJ 1981 最大点覆盖问题(极角排序)

Posted liylho

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1981 最大点覆盖问题(极角排序)相关的知识,希望对你有一定的参考价值。

Circle and Points
Time Limit: 5000MS   Memory Limit: 30000K
Total Submissions: 8346   Accepted: 2974
Case Time Limit: 2000MS

Description

You are given N points in the xy-plane. You have a circle of radius one and move it on the xy-plane, so as to enclose as many of the points as possible. Find how many points can be simultaneously enclosed at the maximum. A point is considered enclosed by a circle when it is inside or on the circle. 
技术分享图片 
Fig 1. Circle and Points

Input

The input consists of a series of data sets, followed by a single line only containing a single character ‘0‘, which indicates the end of the input. Each data set begins with a line containing an integer N, which indicates the number of points in the data set. It is followed by N lines describing the coordinates of the points. Each of the N lines has two decimal fractions X and Y, describing the x- and y-coordinates of a point, respectively. They are given with five digits after the decimal point. 

You may assume 1 <= N <= 300, 0.0 <= X <= 10.0, and 0.0 <= Y <= 10.0. No two points are closer than 0.0001. No two points in a data set are approximately at a distance of 2.0. More precisely, for any two points in a data set, the distance d between the two never satisfies 1.9999 <= d <= 2.0001. Finally, no three points in a data set are simultaneously very close to a single circle of radius one. More precisely, let P1, P2, and P3 be any three points in a data set, and d1, d2, and d3 the distances from an arbitrarily selected point in the xy-plane to each of them respectively. Then it never simultaneously holds that 0.9999 <= di <= 1.0001 (i = 1, 2, 3). 

Output

For each data set, print a single line containing the maximum number of points in the data set that can be simultaneously enclosed by a circle of radius one. No other characters including leading and trailing spaces should be printed.

Sample Input

3
6.47634 7.69628
5.16828 4.79915
6.69533 6.20378
6
7.15296 4.08328
6.50827 2.69466
5.91219 3.86661
5.29853 4.16097
6.10838 3.46039
6.34060 2.41599
8
7.90650 4.01746
4.10998 4.18354
4.67289 4.01887
6.33885 4.28388
4.98106 3.82728
5.12379 5.16473
7.84664 4.67693
4.02776 3.87990
20
6.65128 5.47490
6.42743 6.26189
6.35864 4.61611
6.59020 4.54228
4.43967 5.70059
4.38226 5.70536
5.50755 6.18163
7.41971 6.13668
6.71936 3.04496
5.61832 4.23857
5.99424 4.29328
5.60961 4.32998
6.82242 5.79683
5.44693 3.82724
6.70906 3.65736
7.89087 5.68000
6.23300 4.59530
5.92401 4.92329
6.24168 3.81389
6.22671 3.62210
0

Sample Output

2
5
5
11

Source

题意:给出n个点,问用一个单位圆最多能覆盖多少个点。
思路:把每一个点扩展成单位圆,相交圆会形成相交弧,只需要判断弧被覆盖的最大次数即可,因为弧如果被覆盖,那么以弧上的点为圆心,必然也能覆盖到原来点。

N^2枚举,保存每段弧的极角范围及端点方向,然后按上端点在前,下端点在后,从大到小对极角排序,从头扫描一遍。

若经过上端点:ans++ 否则:ans--,取ans最大值即可。

代码:

 1 //#include"bits/stdc++.h"
 2 #include<sstream>
 3 #include<iomanip>
 4 #include"cstdio"
 5 #include"map"
 6 #include"set"
 7 #include"cmath"
 8 #include"queue"
 9 #include"vector"
10 #include"string"
11 #include"cstring"
12 #include"time.h"
13 #include"iostream"
14 #include"stdlib.h"
15 #include"algorithm"
16 #define db double
17 #define ll long long
18 #define vec vectr<ll>
19 #define mt  vectr<vec>
20 #define ci(x) scanf("%d",&x)
21 #define cd(x) scanf("%lf",&x)
22 #define cl(x) scanf("%lld",&x)
23 #define pi(x) printf("%d\n",x)
24 #define pd(x) printf("%f\n",x)
25 #define pl(x) printf("%lld\n",x)
26 //#define rep(i, x, y) for(int i=x;i<=y;i++)
27 #define rep(i, n) for(int i=0;i<n;i++)
28 const int N   = 1e4+ 5;
29 const int mod = 1e9 + 7;
30 const int MOD = mod - 1;
31 const int inf = 0x3f3f3f3f;
32 const db  PI  = acos(-1.0);
33 const db  eps = 1e-10;
34 using namespace std;
35 struct P
36 {
37     db x,y;
38     db ang;
39     bool in;
40 };
41 P a[N],b[N];
42 db dis(P a,P b){
43     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
44 }
45 int cmp(P a,P b){
46     if(a.ang==b.ang) return a.in>b.in;//上端点在前
47     return a.ang>b.ang;
48 }
49 int main()
50 {
51     int n;
52     while(scanf("%d",&n)==1,n)
53     {
54         int ans=1;
55         for(int i=1;i<=n;i++) cd(a[i].x),cd(a[i].y);
56         for(int i=1;i<=n;i++)
57         {
58             int p=0;
59             for(int j=1;j<=n;j++){
60                 if(i==j||dis(a[i],a[j])>2.0+eps) continue;
61                 db ang=atan2(a[i].x-a[j].x,a[i].y-a[j].y);//i于j的极角
62                 db tha=acos(dis(a[i],a[j])/2.0);//极角波动范围
63                 b[p].ang=ang+tha+2*PI,b[p++].in=1;//上端点
64                 b[p].ang=ang-tha+2*PI,b[p++].in=0;//下端点
65             }
66             sort(b,b+p,cmp);
67             int tmp=1;
68             for(int j=0;j<p;j++){
69                 if(b[j].in==1) tmp++;
70                 else tmp--;
71                 ans=max(tmp,ans);
72             }
73         }
74         pi(ans);
75     }
76     return 0;
77 }

 

 

 




以上是关于POJ 1981 最大点覆盖问题(极角排序)的主要内容,如果未能解决你的问题,请参考以下文章

poj1696(极角排序,贪心)

POJ 3348 Cows | 凸包模板题

Scrambled Polygon POJ - 2007(极角排序)

挑战程序设计竞赛 3.6 与平面和空间打交道的计算几何

POJ 1696 Space Ant

Wall--POJ1113(极角排序+求凸包)