• 几何模板


    1:圆的k次交面积(n个圆,area[i]代表被覆盖i次及以上的面积)

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 1010
    typedef long long ll;
    const double eps=1e-8;
    const double PI=acos(-1);
    int n;
    double sqr(double x){//平方
        return x*x;
    }
    int dcmp(double x){//判断与0的大小关系,小于0返回-1,大于0返回1,等于0返回0
        if(fabs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    struct Circle{//
        double x,y,r,angle;
        int d;
        Circle(){d = 1;}
        Circle(double _x,double _y,double _angle=0,int t=0){
            x=_x; y=_y; angle=_angle; d=t;
        }
        void get(){
            scanf("%lf%lf%lf",&x,&y,&r);
        }
    };
    Circle cir[maxn],tp[maxn<<1];
    double area[maxn];//area[i]代表覆盖i次及以上的面积
    double dis(Circle a,Circle b){
        return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
    }
    double cross(Circle p0,Circle p1,Circle p2){
        return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
    }
    bool Cir_inter_Cir(Circle c1,double r1,Circle c2,double r2,Circle &p1,Circle &p2){
        double d=dis(c1,c2);
        if(d<fabs(r1-r2)-eps || d>r1+r2+eps) return false;
        double cosa=(r1*r1+d*d-r2*r2)/(2*r1*d);
        double sina=sqrt(max(0.,1.-cosa*cosa));
        p1=c1; p2=c1;
        p1.x+=r1/d*((c2.x-c1.x)* cosa+(c2.y-c1.y)*-sina);
        p1.y+=r1/d*((c2.x-c1.x)* sina+(c2.y-c1.y)* cosa);
        p2.x+=r1/d*((c2.x-c1.x)* cosa+(c2.y-c1.y)* sina);
        p2.y+=r1/d*((c2.x-c1.x)*-sina+(c2.y-c1.y)* cosa);
        return true; 
    }
    bool circmp(const Circle& u,const Circle& v){
        return dcmp(u.r-v.r)<0;
    }
    bool cmp(const Circle& u,const Circle& v){
        if(dcmp(u.angle-v.angle)) return u.angle<v.angle;
        return u.d>v.d;
    }
    double calc(Circle cir,Circle cp1,Circle cp2){
        double ans=(cp2.angle-cp1.angle)*sqr(cir.r)-cross(cir,cp1,cp2)+cross(Circle(0,0),cp1,cp2);
        return ans/2;
    }
    void CirUnion(Circle cir[],int n){
        Circle cp1,cp2;
        sort(cir,cir+n,circmp);
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                if(dcmp(dis(cir[i],cir[j])+cir[i].r-cir[j].r)<=0) cir[i].d++;
        for(int i=0;i<n;i++){
            int tn=0,cnt=0;
            for(int j=0;j<n;j++){
                if(i==j) continue;
                if(!Cir_inter_Cir(cir[i],cir[i].r,cir[j],cir[j].r,cp2,cp1)) continue;
                cp1.angle=atan2(cp1.y-cir[i].y,cp1.x-cir[i].x);
                cp2.angle=atan2(cp2.y-cir[i].y,cp2.x-cir[i].x);
                cp1.d=1;  tp[tn++]=cp1;
                cp2.d=-1; tp[tn++]=cp2;
                if(dcmp(cp1.angle-cp2.angle)>0) cnt++;
            }
            tp[tn++]=Circle(cir[i].x-cir[i].r,cir[i].y,PI,-cnt);
            tp[tn++]=Circle(cir[i].x-cir[i].r,cir[i].y,-PI,cnt);
            sort(tp,tp+tn,cmp);
            int p,s=cir[i].d+tp[0].d;
            for(int j=1;j<tn;j++){
                p=s; s+=tp[j].d;
                area[p]+=calc(cir[i],tp[j-1],tp[j]);
            }
        }
    }
    int main(){
        int T;
      cin >> T;
      while(T--){
        cin >> n;
        for(int i = 0;i < n;i++){
          cir[i].get();
        }
        memset(area,0,sizeof(area));
        CirUnion(cir,n);
        for(int i = 1;i <= n;i++)cout << area[i] << endl;
      }
        return 0;
    }
    View Code
  • 相关阅读:
    mysql_fetch_array()和mysql_fetch_assoc()两个函数的区别
    在vmware workstation7上安装centos5.5的一些问题
    如何在CentOS下安装VMwareTools工具
    ResultSetMetaData类的介绍
    火狐快捷键
    ResultSetMetaData类的介绍
    jstl标签的使用
    e.printStackTrace()介绍
    mysql初学指南
    在SQL server中,怎么区别char跟varchar?
  • 原文地址:https://www.cnblogs.com/cherish-lin/p/11772177.html
Copyright © 2020-2023  润新知