每个圆盘只会受到后边的圆盘的影响
所以算一下每个圆盘和后边的圆盘相交的圆心角,然后求个并即可
可以用余弦定理
复杂度n^2 log n
注意特判没有交-_-
#include<iostream> #include<cstring> #include<ctime> #include<cmath> #include<algorithm> #include<iomanip> #include<cstdlib> #include<cstdio> #include<map> #include<bitset> #include<set> #include<stack> #include<vector> #include<queue> using namespace std; #define MAXN 1010 #define MAXM 1010 #define ll long long #define eps 1e-8 #define MOD 1000000007 #define INF 1000000000 const double pi=acos(-1); struct cir{ double x; double y; double r; }; struct itv{ double l; double r; itv(){ } itv(double _l,double _r){ l=_l; r=_r; } friend bool operator <(itv x,itv y){ return x.l<y.l; } }; itv a[MAXN*2]; cir c[MAXN]; double ans; int tot; int n; double sq(double x){ return x*x; } double dis(cir x,cir y){ return sqrt(sq(x.x-y.x)+sq(x.y-y.y)); } double cal(){ int i; double re=0; sort(a+1,a+tot+1); double r=-pi; for(i=1;i<=tot;i++){ if(a[i].l>r){ re+=a[i].l-r; } r=max(r,a[i].r); } re+=pi-r; return re; } int main(){ int i,j; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%lf%lf%lf",&c[i].r,&c[i].x,&c[i].y); } for(i=n;i;i--){ bool flag=0; tot=0; for(j=i+1;j<=n;j++){ if(dis(c[i],c[j])<c[i].r+c[j].r){ if(dis(c[i],c[j])+c[i].r<=c[j].r){ flag=1; break; }else if(dis(c[i],c[j])+c[j].r<=c[i].r){ }else{ double angf=acos((sq(c[i].r)+sq(dis(c[i],c[j]))-sq(c[j].r))/(2*c[i].r*dis(c[i],c[j]))); double ang=atan2(c[j].y-c[i].y,c[j].x-c[i].x); double l=ang-angf,r=ang+angf; if(l<-pi){ a[++tot]=itv(l+2*pi,pi); a[++tot]=itv(-pi,r); }else if(r>pi){ a[++tot]=itv(l,pi); a[++tot]=itv(-pi,r-2*pi); }else{ a[++tot]=itv(l,r); } } } } if(flag){ continue ; } ans+=cal()*c[i].r; } printf("%.3lf\n",ans); return 0; } /* */