HDU——1077 Catching fish(幾何問題)

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

解題思路:

枚舉畫圓 , 記錄單位圓最多可以圈住的點的數量。
枚舉選取其中兩個點 , 如果兩個點的距離小於2,則證明這兩個點可以在同一個圓裏面(注意:這裏隱藏了 從每個最少放兩個點的情況考慮 , 但是最後結果也有可能是 最多隻能圈住一個點 ,這點對應在代碼中 maxsum 的初值設定問題)。此時以這兩個點可以確定一個半徑爲1 的 單位圓 , 主要求出圓心位置即可。然後在一個枚舉 , 對比記錄與這個圓心距離小於 1 的點的個數。

代碼:

//枚舉圓心
/* 選取任意兩個點 , 求取兩點所在的以 1 爲半徑的圓的圓心, 作圓 , 計算該圓中有多少點。*/
#include <cstdio>
#include <math.h>
using namespace std;

double x[305];
double y[305];
int n;

double distance1(int i , int  j){   //求 距離的平方
    double dis = 0;
    dis = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
    return dis;
}

void getCenter(int i , int j){   //求 圓心
    x[n+1] = (x[i] + x[j]) / 2;  //中心點
    y[n+1] = (y[i] + y[j]) / 2;

    double k = -1 *  (x[i] - x[j])/(y[i] - y[j]);
    //k1 * k2 = -1
    //float k2 = -1 / k1;   //中垂線的 k
    double rad = atan(k);

    double len = sqrt(1 - distance1( i , n + 1));   //中點 到 圓心 的距離

    x[n] = x[n+1] + (len * cos(rad));
    y[n] = y[n+1] + (len * sin(rad));

}

int main(){
    //freopen("D://testData//1077.txt","r",stdin);// 數據太多 , 直接從文件讀
    int t , i , j , maxsum = 0, ans;

    scanf("%d" , &t);
    while(t -- ){
       ans = 0;
       maxsum = 1;    //!!!!一定不能是 0 呀 , 因爲我們一下考慮的情況都是每個圈裏最少有2個點 , 將一個點的都沒有考慮。
       scanf("%d" , &n);

       for(i = 0 ; i < n ; i ++){
            scanf("%lf %lf" , &x[i] , &y[i]);
       }

       for(i = 0 ; i < n ; i ++){
            for(j = i + 1 ; j < n ; j ++){
                ans = 0;
                if(distance1(i , j) > 4){   //如果兩點之間的距離的平方大於 4 , 那麼就不考慮這個情況。
                    continue;
                }

                getCenter(i ,j);

                for(int k = 0 ; k < n ; k ++){
                    if(distance1(k , n) <= 1.001)
                        ans ++;
                }
                if(ans > maxsum)
                    maxsum = ans;
            }
       }
       printf("%d\n" , maxsum);

    }
    return 0;
}
發佈了89 篇原創文章 · 獲贊 138 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章