1. 程式人生 > >HDU 1077 Catching Fish(用單位圓盡可能圍住多的點)

HDU 1077 Catching Fish(用單位圓盡可能圍住多的點)

bits fine cau ron esc rds cas nts blank

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1077

Catching Fish

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2636 Accepted Submission(s): 969


Problem Description Ignatius likes catching fish very much. He has a fishnet whose shape is a circle of radius one. Now he is about to use his fishnet to catch fish. All the fish are in the lake, and we assume all the fish will not move when Ignatius catching them. Now Ignatius wants to know how many fish he can catch by using his fishnet once. We assume that the fish can be regard as a point. So now the problem is how many points can be enclosed by a circle of radius one.

Note: If a fish is just on the border of the fishnet, it is also caught by Ignatius.

Input The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case starts with a positive integer N(1<=N<=300) which indicate the number of fish in the lake. Then N lines follow. Each line contains two floating-point number X and Y (0.0<=X,Y<=10.0). You may assume no two fish will at the same point, and no two fish are closer than 0.0001, no two fish in a test case are approximately at a distance of 2.0. In other words, if the distance between the fish and the centre of the fishnet is smaller 1.0001, we say the fish is also caught.

Output For each test case, you should output the maximum number of fish Ignatius can catch by using his fishnet once.

Sample Input 4 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

Sample Output 2 5 5 11

Author Ignatius.L 題目意思: 告訴你一些點,要求你用單位圓盡可能圍住多的點,問你最多圍住多少點? 在單位圓邊緣的點也算圍住 做法: 每次枚舉兩個距離小於2.001的點在單位圓上(距離大於2.001的點不可能在同一個單位圓上) 根據這兩個點的位置,可以確定單位圓圓心的位置,再來計算哪些點到圓心的距離小於等於1.001(就是圍住了哪些點) 然後在每次枚舉得到的圍住的點中找到最大值 就是最多圍住的點數!

註意兩個點可以確定兩個單位圓,有兩個圓心,所以需要算兩次 code:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define max_v 305
double p[max_v][2];
int n;
double dis(double x1,double y1,double x2,double y2)//兩點距離
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double f(int i,int j)
{
    double x1,y1,x2,y2,x3,y3,x4,y4,x5,y5;
    x1=p[i][0];
    y1=p[i][1];

    x2=p[j][0];
    y2=p[j][1];

    double s=dis(x1,y1,x2,y2);
    double xx=(y2-y1)/s;//(xx,yy)相當於與弦長垂直的單位法向量
    double yy=(x1-x2)/s;

    s=s/2.0;
    s=sqrt(1.0-s*s);//圓心與兩點弦長的距離

    x3=(x1+x2)/2.0;
    y3=(y1+y2)/2.0;//(x3,y3)是(x1,y1),(x2,y2)的中點

    int c1=0,c2=0;

    x4=x3+s*xx;
    y4=y3+s*yy;//(x4,y4)現在是圓心
    for(int i=0;i<n;i++)
    {
        if(dis(x4,y4,p[i][0],p[i][1])<1.0001)
            c1++;
    }

    x5=x3-s*xx;
    y5=y3-s*yy;//(x5,y5)現在是圓心
    for(int i=0;i<n;i++)
    {
        if(dis(x5,y5,p[i][0],p[i][1])<1.0001)
            c2++;
    }

    if(c1>c2)
        return c1;
    else
        return c2;

}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf %lf",&p[i][0],&p[i][1]);
        }
        int temp,sum=1;
        
        //暴力,每次讓兩點恰好位於單位圓上,算出圓心。然後找覆蓋點的數目,輸出最大的
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(dis(p[i][0],p[i][1],p[j][0],p[j][1])<2.0001)//距離大於2.0001的點可以不枚舉,因為這兩點肯定不在一個單位圓上
                {
                    temp=f(i,j);
                    if(sum<temp)
                    {
                        sum=temp;
                    }

                }
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}

HDU 1077 Catching Fish(用單位圓盡可能圍住多的點)