几何模板
1:圆的k次交面积(n个圆,area[i]代表被覆盖i次及以上的面积)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }