求红线总长可以用每个圆的周长减去被覆盖的部分
对每个圆i,枚举
j>i
j
>
i
计算圆j覆盖了圆i的长度
若i和j相离/相切或i包含j不考虑
若i被j包含就被完全覆盖
否则是相交的情况如图
圆A和圆B交与C,D,可以算出AE,CE的长度,用余弦定理可以算得cosCAE,用acos,atan2可以算得A被覆盖的一个弧度区间,把所有覆盖的区间求出来后就变成了一个区间覆盖问题
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1100;
const double pi = acos(-1);
const double eps = 1e-9;
const double sqr(const double x){return x*x;}
int n;
struct node
{
double x,y,r;
}a[maxn];
struct interval
{
double l,r;
friend inline bool operator <(const interval x,const interval y)
{
return x.l<y.l;
}
}t[maxn]; int tp;
double ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].r,&a[i].x,&a[i].y);
for(int i=1;i<=n;i++)
{
tp=0; bool fl=true;
for(int j=i+1;j<=n;j++)
{
double dis=sqrt(sqr(a[i].x-a[j].x)+sqr(a[i].y-a[j].y));
if(dis>a[i].r+a[j].r-eps) continue;
if(dis<a[i].r-a[j].r+eps) continue;
if(dis<a[j].r-a[i].r+eps) { fl=false;break; }
double dec=acos((sqr(a[i].r)+sqr(dis)-sqr(a[j].r))/(2.0*a[i].r*dis));
double mid=atan2(a[j].y-a[i].y,a[j].x-a[i].x);
double l=mid-dec,r=mid+dec;
if(r>pi) t[++tp]=(interval){-pi,-pi+r-pi},r=pi;
if(l<-pi) t[++tp]=(interval){pi-(-pi-l),pi},l=-pi;
t[++tp]=(interval){l,r};
}
if(!fl) continue;
sort(t+1,t+tp+1);
double las=-pi,sum=0;
for(int j=1;j<=tp;j++)
{
if(las<t[j].l) sum+=t[j].l-las;
las=max(las,t[j].r);
}
sum+=pi-las;
ans+=sum*a[i].r;
}
printf("%.3lf\n",ans);
return 0;
}