# bzoj 1043 下落的圆盘 —— 求圆心角、圆周长

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef double db;
db const Pi=acos(-1.0),eps=1e-8;
int const xn=1005;
int n;
db ans;
struct N{db x,y,r;}p[xn];
struct P{
db l,r;
P(db l=0,db r=0):l(l),r(r) {}
bool operator < (const P &y) const
{return l<y.l;}
}v[xn];
db sqr(db x){return x*x;}
int dmp(db x){if(fabs(x)<=eps)return 0; return x>eps?1:-1;}
db dis(N a,N b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&p[i].r,&p[i].x,&p[i].y);
for(int i=1;i<=n;i++)
{
bool fl=0; int cnt=0;
for(int j=i+1;j<=n;j++)
{
db x1=p[i].x,x2=p[j].x,y1=p[i].y,y2=p[j].y,r1=p[i].r,r2=p[j].r,d=dis(p[i],p[j]);
if(dmp(d+p[i].r-p[j].r)<=0){fl=1; break;}//i in j
if(dmp(d+p[j].r-p[i].r)<=0||dmp(d-p[i].r-p[j].r)>=0)continue;//j in i
db fx=atan2(y2-y1,x2-x1);
db th=acos((sqr(r1)+sqr(d)-sqr(r2))/(2*r1*d));//acos
db l=fx-th,r=fx+th;
while(l<0)l+=2*Pi; while(r<0)r+=2*Pi;
while(l>2*Pi)l-=2*Pi; while(r>2*Pi)r-=2*Pi;
if(dmp(l-r)<=0)v[++cnt]=P(l,r);
else v[++cnt]=P(0,r),v[++cnt]=P(l,2*Pi);
}
if(fl)continue;//
sort(v+1,v+cnt+1);
db mx=0,g=0;
for(int j=1;j<=cnt;j++)
{
if(dmp(v[j].r-mx)<=0)continue;
if(dmp(v[j].l-mx)>0)g+=v[j].l-mx;
mx=v[j].r;
}
ans+=p[i].r*(g+2*Pi-mx);//
}
printf("%.3f\n",ans);
return 0;
}

posted @ 2018-12-19 18:07  Zinn  阅读(203)  评论(0编辑  收藏  举报