ZOJ 3993

题目链接: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,用数组就不会。

原文地址:https://www.cnblogs.com/dilthey/p/7788017.html