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时,圆内所有点的概率都相同。
代码:
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; }
相关文章推荐
- [ACM] ZOJ 3329 One Person Game (概率DP,有环,巧妙转化)
- ZOJ - 3993 - Safest Buildings(概率,分类讨论)
- ZOJ 2797 106 miles to Chicago(多校连萌,用最短路径求概率问题)
- ZOJ 3993 Safest Buildings(概率 数学)
- ZOJ 3329 One Person Game(概率问题)
- 2017 CCPC 秦皇岛 & ZOJ 3993 - Safest Buildings (概率+规律)
- [dp问题] Poj 1014 & Zoj 1149 (Dividing) 解题报告(转)
- SVM入门(六)线性分类器的求解——问题的转化,直观角度
- ZOJ1005 Jug问题 运行结果有误?
- ActionForm空字段问题和struts类型转化器
- 传球(概率问题)
- 贝叶斯垃圾邮件分类问题中联合概率的推导
- ZOJ 3329 One Person Game 概率dp
- MFC中Unicode与多字节编码中遇到的CString与char或char*的转化问题
- zoj 1010 Area【线段相交问题】
- ZOJ问题
- Jox(解决了日期格式转化和导出XML中文乱码问题)
- 九度OJ 1006:ZOJ问题 (递归)
- ZOJ 1586 : QS Network - prim算法解决最小生成树问题
- 一个有趣的概率问题(阿里2012校园招聘——运维笔试)