bzoj1043: [HAOI2008]下落的圆盘

来源:互联网 发布:东方有线网络 客服电话 编辑:程序博客网 时间:2024/04/18 23:40

传送门
看到数据范围不大,暴力走起。
枚举每一个圆,如果被完全覆盖直接退出。
否则如果被覆盖掉一部分就求出覆盖区间。
然后就是sb的区间覆盖问题了。

#include<cmath> #include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define pi acos(-1)using namespace std;int n,top;double ans,r[1005],x[1005],y[1005];struct line{double l,r;}q[2005];bool cmp(line a,line b){    return a.l<b.l;}double sqr(double x){return x*x;}double dis(int a,int b){    return sqrt(sqr(x[a]-x[b])+sqr(y[a]-y[b]));}bool init(int a,int b){    return r[a]>=r[b]+dis(a,b);}void add(int a,int b){    double d,t,st,l;    d=dis(a,b);    t=(sqr(r[a])-sqr(r[b])+sqr(d))/(2*d);//余弦定理    st=atan2(x[a]-x[b],y[a]-y[b]);    l=acos(t/r[a]);    q[++top]=(line){st-l,st+l};}double cal(int x){    for (int i=x+1;i<=n;i++)        if (init(i,x)) return 0;    top=0;    for (int i=x+1;i<=n;i++)        if (!init(x,i)&&r[x]+r[i]>=dis(x,i))            add(x,i);    for (int i=1;i<=top;i++){        if (q[i].l<0) q[i].l+=2*pi;        if (q[i].r<0) q[i].r+=2*pi;        if (q[i].l>q[i].r){            q[++top]=(line){0,q[i].r};            q[i].r=2*pi;        }    }    sort(q+1,q+top+1,cmp);    double tmp=0,now=0;    for (int i=1;i<=top;i++)        if (q[i].l>now){            tmp+=q[i].l-now;            now=q[i].r;        }        else now=max(now,q[i].r);    tmp+=2*pi-now;    return r[x]*tmp;}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++)        scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);    for (int i=1;i<=n;i++)        ans+=cal(i);    printf("%.3lf",ans);}
0 0
原创粉丝点击