[POJ 1981円と点(点まで覆う単位円)

説明

あなたは、xy平面にNポイントが与えられています。あなたは、半径1の円を持っているし、可能な限りのポイントの多くを囲むように、xy平面上に移動します。同時に最大で囲むことができますどのように多くのポイントを見つけます。ポイントは、それが内側または円上にある場合、円で囲まれたと考えられます。 
 
図1.サークルとのポイント

入力

入力は単一の文字「0」、入力の終了を示す含む単一の行に続くデータセットのシリーズからなります。各データセットは、データセット内のポイントの数を示す整数Nを含む行から始まります。これは、点の座標を記述するN行が続いています。Nラインの各々は、それぞれ、点のx座標とy座標を記述する二つ小数XおよびYを有します。彼らは、小数点以下5桁で与えられています。 

あなたは、1 <= Nをとることができる<= 300、0.0 <= X <= 10.0、0.0 <= Y <= 10.0。どの2つのポイントは0.0001より近くではありません。データセット内の2つの点は、2.0の距離で約ありません。より正確には、データセット内の任意の2点のため、両者間の距離dは、1.9999 <= D <= 2.0001を満たすことはありません。最後に、データセットには3つの点が同時に半径一方の単一の円に非常に近接していません。より正確には、それぞれP1、P2、及びP3は、任意の3つのデータセット内のポイント、D1、D2であるとすると、XY平面内で任意に選択された点からの距離D3それらのそれぞれに。それは決して同時に保持する0.9999 <=ジ<= 1.0001(I = 1、2、3)。 

出力

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

SOLUTION:

这题用来当模板

已经知道半径为1

O(n^3)的做法:

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

用到了两个函数

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

O(n^2log(n))

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

 

CODE:

以下为第二中做法

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 310
#define LL long long
#define INF 0xfffffff
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;
struct point
{
    double x,y;
    point(double x = 0,double y =0 ):x(x),y(y) {}
} p[N];
struct node
{
    double ang;
    int in;
} arc[N*N];
double dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int dcmp(double x)
{
    if(fabs(x)<eps)return 0;
    else return x<0?-1:1;
}
bool cmp(node a,node b)
{
    if(dcmp(a.ang-b.ang)==0)
        return a.in>b.in;
    return dcmp(a.ang-b.ang)<0;
}
int main()
{
    int i,j,n;
    while(scanf("%d",&n)&&n)
    {
        for(i = 1 ; i <= n; i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        int g = 0;
        int ans = 0,maxz = 1;
        for(i = 1; i <= n ; i++)
        {
            ans = 0;
            g = 0;
            for(j = 1; j <= n ; j++)
            {
                if(dis(p[i],p[j])>2.0) continue;
                double ang1 = atan2(p[i].y-p[j].y,p[i].x-p[j].x);
                double ang2 = acos(dis(p[i],p[j])/2);
                arc[++g].ang = ang1-ang2;//这里角度的算法很巧妙
                arc[g].in = 1;
                arc[++g].ang = ang1+ang2;
                arc[g].in = -1;
            }
            sort(arc+1,arc+g+1,cmp);

            //cout<<g<<endl;
            for(j = 1 ; j <= g;j++)
            {
                ans+=arc[j].in;
                maxz = max(maxz,ans);
            }
        }
        printf("%d\n",maxz);
    }
    return 0;
}

  

 

 

 

 

おすすめ

転載: www.cnblogs.com/zhangbuang/p/11184537.html