zoukankan      html  css  js  c++  java
  • bzoj2178: 圆的面积并

    Description

    给出N个圆,求其面积并

    Input

    先给一个数字N ,N< = 1000 接下来是N行是圆的圆心,半径,其绝对值均为小于1000的整数

    Output

    面积并,保留三位小数
    简单说就是去除被包含的圆,求出每个圆的圆周未被其他圆覆盖的圆弧,求对应弓形的面积以及弓形的弦与原点构成的三角形的有向面积。
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long double ld;
    int n;
    const ld pi=acos(-1.l),_2pi=pi*2;
    struct itv{ld l,r;}is[2007];
    bool operator<(itv x,itv y){return x.l<y.l;}
    int ip;
    ld ans=0;
    ld maxs(ld&a,ld b){if(a<b)a=b;}
    struct cir{
        int x,y,r;
        void init(){scanf("%d%d%d",&x,&y,&r);}
        bool in(cir w){
            int a=x-w.x,b=y-w.y;
            return sqrt(a*a+b*b)+r-1e-7l<w.r;
        }
        bool cross(cir w){
            int a=x-w.x,b=y-w.y;
            return sqrt(a*a+b*b)<r+w.r;
        }
        ld fix(ld x){
            while(x<0)x+=_2pi;
            while(x>_2pi)x-=_2pi;
            return x;
        }
        void cal(cir w){
            ld xd=w.x-x,yd=w.y-y,d=sqrt(xd*xd+yd*yd);
            ld a=atan2(yd,xd);
            ld b=acos((r*r+d*d-w.r*w.r)/(2*r*d));
            ld l=fix(a-b),r=fix(a+b);
            if(l<r)is[ip++]=(itv){l,r};
            else is[ip++]=(itv){0,r},is[ip++]=(itv){l,_2pi};
        }
        inline void g1(ld a){
            ans+=(a-sin(a))*r*r;
        }
        inline void g2(ld L,ld R){
            ans+=((x+cos(L)*r)*(y+sin(R)*r)-(x+cos(R)*r)*(y+sin(L)*r));
        }
        void get(){
            if(!ip){
                ans+=pi*r*r*2;
                return;
            }
            std::sort(is,is+ip);
            ld L,R=-1,R1;
            for(int i=0,j=0;i<ip;i=j){
                R1=R;L=is[i].l;R=is[i].r;
                while(j<ip&&is[j].l<=R)maxs(R,is[j++].r);
                if(R1!=-1)g1(L-R1),g2(R1,L);
            }
            g1(is[0].l+_2pi-R),g2(R,is[0].l+_2pi);
        }
    }cs[1007];
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;++i)cs[i].init();
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j)if(i!=j&&cs[i].in(cs[j])){
                cs[i--]=cs[--n];
                break;
            }
        }
        for(int i=0;i<n;++i){
            ip=0;
            for(int j=0;j<n;++j)if(i!=j&&cs[i].cross(cs[j])){
                cs[i].cal(cs[j]);
            }
            cs[i].get();
        }
        printf("%.3Lf",ans/2.);
        return 0;
    }
  • 相关阅读:
    聪明的质检员 (二分)
    分巧克力(二分)
    产生冠军 HDU
    Legal or Not HDU
    确定比赛名次 HDU
    最短路径问题 HDU
    dijkstra算法为什么不能有负边?
    最短路 HDU
    dijkstra算法 模板
    Floyd算法模板--详解
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6146757.html
Copyright © 2011-2022 走看看