Safest Buildings ZOJ - 3993(計算幾何+思維)

Safest Buildings ZOJ - 3993

PUBG is a multiplayer online battle royale video game. In the game, up to one hundred players parachute onto an island and scavenge for weapons and equipment to kill others while avoiding getting killed themselves. BaoBao is a big fan of the game, but this time he is having some trouble selecting the safest building.

There are buildings scattering on the island in the game, and we consider these buildings as points on a two-dimensional plane. At the beginning of each round, a circular safe area whose center is located at (0, 0) with radius will be spawned on the island. After some time, the safe area will shrink down towards a random circle with radius (). The whole new safe area is entirely contained in the original safe area (may be tangent to the original safe area), and the center of the new safe area is uniformly chosen within the original safe area.

The buildings covered by the new safe area is called the safe buildings. Given the radius of the safe areas and the positions of the buildings, BaoBao wants to find all the buildings with the largest probability to become safe buildings.
Input

There are multiple test cases. The first line of input contains an integer , indicating the number of test cases. For each test case:

The first line contains three integers (), and (), indicating the number of buildings and the radius of two safe circles.

The following lines each contains 2 integers and (), indicating the coordinate of the buildings. Here we assume that the center of the original safe circle is located at , and all the buildings are inside the original circle.

It’s guaranteed that the sum of over all test cases will not exceed 5000.
Output

For each test case output two lines.

The first line contains an integer , indicating the number of buildings with the highest probability to become safe buildings.

The second line contains integers separated by a space in ascending order, indicating the indices of safest buildings.

Please, DO NOT output extra spaces at the end of each line.
Sample Input

2
3 10 5
3 4
3 5
3 6
3 10 4
-7 -6
4 5
5 4

Sample Output

1
1
2
2 3

題意:

原本有一個半徑爲R的圓形的圈,圈裏面是安全區域,大圈內部有一些建築物,給定這些建築物的座標,現在給定一個半徑爲r(rRr\le R)的小圈,圓心可以爲大圈內的任意一點,這樣小圈變成縮小後的安全區域,問縮小範圍後,仍然處在安全區域的概率最大的建築物是啥,輸出個數和每個建築物的編號

分析:

大致應該分爲兩種情況:

一、 當小圓的直徑2r小於大圓的半徑R的時候,對於一個點而言,它所處的所有可能的安全區域,應該是讓這個點在小圓的邊上,然後小圓繞這個點轉一圈所得到的中等圓,此圓的半徑爲2r
如圖所示
在這裏插入圖片描述
那麼這個時候的邊界條件就是圖中紅色圓與大圓想內切的時候,綠圈表示的是點可以在的邊界範圍,因爲在這個範圍上以及在這個範圍內,任意點的所有安全區域都可以構成一個圖中紅色的中等圓,因此只需要比較半徑和圓心距即可,設點到圓心的距離爲dis,所以只需要比較如果R-dis>=2r說明這裏面的點都是等可能安全的並且都是安全可能性最大,否則再灰色區域的點,一定無法構成一個完整的紅色圓,安全可能性就小,如果綠色圈內沒有點,就選取裏圓心近的點,越近越好。

二、如果小圓直徑2r大於大圓的半徑R,此時如果讓小圓內切着大圓轉一圈,那麼中心一定可以有個圓形區域,它始終包含,那麼這個區域內的點,就是可能性最大的點,所以只需要判斷是否在這個區域即可,判斷是否在這個區域仍然是比較距離

在這裏插入圖片描述
圖中綠色區域就是安全性最大的區域,即無論小圓怎麼轉始終會包括的公共區域,那麼根據圖可以知道只要dis+R<=2r即可,同理如果沒有,就選擇離圓心越近越好

code:

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-6;
struct node{
    int x,y,id;
    double dis;
    bool operator < (const node & a)const{
        return dis < a.dis;
    }
}p[110];
vector<int> vec;

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        vec.clear();
        int n,R,r;
        scanf("%d%d%d",&n,&R,&r);
        for(int i = 1; i <= n; i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            p[i].dis = sqrt(1.0 * p[i].x * p[i].x + 1.0 * p[i].y * p[i].y);
            p[i].id = i;
        }
        sort(p+1,p+1+n);
        if(R > 2 * r){
            for(int i = 1; i <= n; i++){
                if(R - p[i].dis >= 2.0 * r)
                    vec.push_back(p[i].id);
            }//找範圍內的點
            if(vec.size() == 0){//如果範圍內沒有,有找離圓心距離最近的點
                double t = p[1].dis;
                for(int i = 1; i <= n; i++){
                    if(t == p[i].dis)
                        vec.push_back(p[i].id);
                }
            }
        }
        else{
            for(int i = 1; i <= n; i++){
                if(p[i].dis + R <= 2.0 * r)
                    vec.push_back(p[i].id);
            }
            if(vec.size() == 0){
                double t = p[1].dis;
                for(int i = 1; i <= n; i++){
                    if(t == p[i].dis)
                        vec.push_back(p[i].id);
                }
            }
        }
        sort(vec.begin(),vec.end());
        printf("%d\n",vec.size());
        for(int i = 0; i < vec.size(); i++){
            printf("%d%c",vec[i],i == vec.size() - 1 ? '\n' : ' ');
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章