您的位置:首页 > 其它

ZOJ-3993(概率转化为面积问题)

2017-11-13 20:52 281 查看
题目:

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),给n个建筑物,要求输出安全率最高的建筑的数目和编号

思路:

第一点:以每一个建筑为圆心,以r为半径作一个圆O1,这个圆O1内或者圆上的点都可以它本身为圆心,以r为半径作一个圆O2使这个建筑在这个圆O2内(安全区内),所以题目可以转化为 看哪个建筑的圆O1的面积大。如图A,B两个建筑物,明显A的圆O1面积大于B的圆O1面积,A的概率就大于B(这只是这样理解,还不是最终思路)



第二点:因为题意要求这个小圆(安全区)一定全部在大圆内,如图,大圆圆心0与建筑物A的距离为dis,圆A上离圆心最远的点到圆心的距离为dis+r,只要dis+2*r<=R,就能满足这个圆A上所有的点做一个以r为半径的小圆,都能在大圆内(即满足条件)。如果都不满足这个条件,只要比较每一建筑到圆心的距离就行,谁距离近,就概率大。



然后这个dis+2*r<=R,并不可以直接比较,因为如果求dis用了sqrt,即使用double储存,也会损失精度,A不了。所以可以变为 比较 dis*dis<=(R-2*r)*(R-2*r),用int储存。

第三点:还有一个特例,当R=r时,圆内所有点的概率都相同。

代码:

#include <iostream>
#include <stdio.h>
#include <math.h>

using namespace std;

const int maxn = 100+5;
const int INF = 0x3f3f3f3f;
int x[maxn],y[maxn];

int T,n,R,r,m,ans[maxn];
int dis[maxn],flag;

int sum(int i)
{
int sum1,sum2;
sum1=dis[i];
sum2=R*R+4*r*r-4*R*r;
if(sum1<=sum2)
return 1;
return 0;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&R,&r);
flag =INF;
m=0;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&x[i],&y[i]);
dis[i] =x[i]*x[i]+y[i]*y[i];
flag=min(dis[i],flag);
}

if(R!=r)
{
for(int i=1; i<=n; i++)
{
if(sum(i))
ans[m++]=i;
}
if(m)
{
printf("%d\n",m);
for(int i=0; i<m-1; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[m-1]);
}
else
{
for(int i=1; i<=n; i++)
{
if(dis[i]==flag)
ans[m++]=i;
}
printf("%d
4000
\n",m);
for(int i=0; i<m-1; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[m-1]);

}
}
else
{
printf("%d\n",n);
for(int i=1; i<n; i++)
printf("%d ",i);
printf("%d\n",n);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息