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( r R r\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;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/82793190