Description
有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红色线条的总长度即为所求.
Input
n ri xi y1 ... rn xn yn
Output
最后的周长,保留三位小数
Sample Input
2
1 0 0
1 1 0
1 0 0
1 1 0
Sample Output
10.472
HINT
数据规模
n<=1000
因为n只有1000.所以对于每个圆。处理其后面落下来的环覆盖的部分,然后求和即可。
反三角函数 atan2(y,x)
#include<cmath> #include<cstdio> #include<algorithm> using namespace std; double pi=3.141592653; struct circle { double r; double x,y; }a[1001]; struct cover { double se,ee; }b[10001]; inline bool cmp(cover x,cover y) { if(x.se<y.se) return true; if(x.se==y.se&&x.ee<y.ee) return true; return false; } int main() { int n; scanf("%d",&n); int i,j,k; for(i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].r,&a[i].x,&a[i].y); double ans=0; for(i=1;i<=n;i++) { int p=0; for(j=i+1;j<=n;j++) { double dis=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y); if(dis==0) { if(a[i].r<a[j].r) { p++; b[p].se=0; b[p].ee=double(2)*pi; break; } else continue; } if(dis>(a[i].r+a[j].r)*(a[i].r+a[j].r)) continue; if(dis<(a[i].r-a[j].r)*(a[i].r-a[j].r)) { if(a[i].r<a[j].r) { p++; b[p].se=0; b[p].ee=double(2)*pi; break; } else continue; } double dx=a[j].x-a[i].x,dy=a[j].y-a[i].y; double de=atan2(dy,dx); if(de<0) de=double(2)*pi+de; double dre=acos((a[i].r*a[i].r+dis-a[j].r*a[j].r)/(double(2)*a[i].r*sqrt(dis))); p++; b[p].se=de-dre; b[p].ee=de+dre; if(b[p].se<0&&b[p].ee<0) { b[p].se=double(2)*pi+b[p].se; b[p].ee=double(2)*pi+b[p].ee; } else if(b[p].se<0) { double tse=b[p].se,tee=b[p].ee; b[p].se=double(2)*pi+b[p].se; b[p].ee=double(2)*pi; p++; b[p].se=0; b[p].ee=tee; } else if(b[p].se>double(2)*pi&&b[p].ee>double(2)*pi) { b[p].se-=double(2)*pi; b[p].ee-=double(2)*pi; } else if(b[p].ee>double(2)*pi) { double tse=b[p].se,tee=b[p].ee; b[p].se=tse; b[p].ee=double(2)*pi; p++; b[p].se=0; b[p].ee=tee-double(2)*pi; } } sort(b+1,b+1+p,cmp); double len=0; for(j=1;j<=p;j++) { double l=b[j].se,r=b[j].ee; for(k=j+1;k<=p;k++) { if(b[k].se>r) break; if(b[k].ee>r) r=b[k].ee; } len+=(r-l); j=k-1; } ans+=(double(2)*pi-len)*a[i].r; //printf("%lf\n",len); } printf("%.3lf\n",ans); return 0; }