题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3993
题意:
给出n幢建筑,每个都以一个点表示,给出点坐标。
有一个以原点为圆心,以R为半径的圆,记为圆O,是原始安全范围;
then,安全范围变为在原来那个圆内任意位置的以r为半径的圆(不会超出原来的圆),记为圆P;
求缩圈后,仍在安全范围内的概率最大的,所有的点。
题解:
怎么求概率?
对于一幢建筑(或者说一个点),以其为圆心,做一个以半径为2r的圆Q;
圆Q在圆O内的面积,除以圆O的面积,得到的商即为这个点对应的概率。
显然这个概率,有关于:“点和原点的距离”;
当R>2*r 时,
在以原点为圆心,以R-2*r为半径的圆的范围内的点,安全概率最高且全部相同;
如果不存在这样的点,则越靠近原点越安全;
当R<=2*r时,
在以原点为圆心,以2*r-R为半径的圆的范围内的点,安全概率最高且全部相同;
如果不存在这样的点,则越靠近原点越安全;
AC代码:
#include<bits/stdc++.h> struct Point{ int id; double d; }p[105]; int n; double R,r; int ans[105],ans_cnt; int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%lf%lf",&n,&R,&r); double SameSafe_R = fabs(R-2*r); double mini_d = 0x3f3f3f3f; ans_cnt=0; for(int i=1,x,y;i<=n;i++) { scanf("%d%d",&x,&y); p[i].id=i; p[i].d=sqrt(x*x+y*y); if(p[i].d<=SameSafe_R) ans[ans_cnt++]=p[i].id; if(p[i].d<mini_d) mini_d=p[i].d; } if(ans_cnt>0) { printf("%d ",ans_cnt); for(int i=0;i<ans_cnt;i++) { if(i!=0) printf(" "); printf("%d",ans[i]); } printf(" "); } else { for(int i=1;i<=n;i++) if(p[i].d<=mini_d) ans[ans_cnt++]=p[i].id; printf("%d ",ans_cnt); for(int i=0;i<ans_cnt;i++) { if(i!=0) printf(" "); printf("%d",ans[i]); } printf(" "); } } }
PS.比较奇怪的一点是,用vector会WA,用数组就不会。