2017省选拔(二)poj1981 Circle and Points (数学)

来源:互联网 发布:端口多路复用 编辑:程序博客网 时间:2024/06/05 18:58

直接链接:点击打开链接

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
36.47634 7.696285.16828 4.799156.69533 6.2037867.15296 4.083286.50827 2.694665.91219 3.866615.29853 4.160976.10838 3.460396.34060 2.4159987.90650 4.017464.10998 4.183544.67289 4.018876.33885 4.283884.98106 3.827285.12379 5.164737.84664 4.676934.02776 3.87990206.65128 5.474906.42743 6.261896.35864 4.616116.59020 4.542284.43967 5.700594.38226 5.705365.50755 6.181637.41971 6.136686.71936 3.044965.61832 4.238575.99424 4.293285.60961 4.329986.82242 5.796835.44693 3.827246.70906 3.657367.89087 5.680006.23300 4.595305.92401 4.923296.24168 3.813896.22671 3.622100
Sample Output
25511
题目大意:

在一个区域面积内(最大为10)有很多个点(用坐标表示),用一个单位圆圈点。问呢能圈的最多的点是多少。

题解:

用单位圆圈点,假如一个点的时候,就让它在圆内就可以了。那么如果是两个点呢。那就得看看这两个点的距离了。如果这两个点的距离小于直径的话,那么我有两种选择,一是让这个两个点必须在圆上,俩一个当然可以不在圆上。当然为了能够圈出更多的点的话,我应该让这两个点在圆上才会使得圆有更多的空间去圈别的点(自己想一想这个)。那么程序就来了。每次枚举两个点,找到这两个点的圆心,然后再从n个点中找与圆心的距离小于半径的点。

主要怎么找圆心,这个网上的数学证明上有很多。看一下代码吧。

ps(其实这篇博客是在做这个题好几天之后写的。当再分析的时候发现了一个问题,就是当枚举的两个点的距离小于直径的时候会得出两个圆心的,那么取哪一个呢,但是代码中我当时取了一个就过了啊。希望得到大牛的指点)

#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <cmath>#include <algorithm>#include <queue>using namespace std;double x[500],y[300];double r;int mx,n;double getd(double a1,double a2,double b1,double b2){//    printf("%.5lf %.5lf %.5lf %.5lf \n",a1,b1,a2,b2);//    printf("%.7lf\n",sqrt((a1-a2)*(a1-a2)+(b1-b2)*(b1-b2)));    return sqrt((a1-a2)*(a1-a2)+(b1-b2)*(b1-b2));}void judge(double rx,double ry){    int num=0;    for(int i=0;i<n;i++)    {        //printf("*%d %.7lf %.7lf\n",i,r,getd(x[i],rx,y[i],ry));        if(getd(x[i],rx,y[i],ry)<r+0.0000001)num++;    }    //cout<<num<<endl;    mx=max(num,mx);}void getrh(int i,int j){    double midx=(x[i]+x[j])/2;    double midy=(y[i]+y[j])/2;    double ang=atan2(x[i]-x[j],y[j]-y[i]);    double d=sqrt(1-getd(x[i],midx,y[i],midy)*getd(x[i],midx,y[i],midy));    double rx=midx+d*cos(ang);    double ry=midy+d*sin(ang);    judge(rx,ry);}int main(){    while(~scanf("%d",&n),n)    {        r=1.0;        mx=1;        for(int i=0;i<n;i++)        {            scanf("%lf%lf",&x[i],&y[i]);        }        for(int i=0;i<n;i++)        {            for(int j=i+1;j<n;j++)            {                if(getd(x[i],x[j],y[i],y[j])>2.0)continue;                getrh(i,j);            }        }        printf("%d\n",mx);    }    return 0;}


0 0
原创粉丝点击