题目
计算每个圆对另一个圆的覆盖弧度然后取并集就行了。
求弧度用atan2+余弦定理。
AC Code:
#include<bits/stdc++.h>
#define maxn 1005
#define Pi 3.1415926535897932384626433832795
#define inf 0x3f3f3f3f
using namespace std;
double sqr(double a){ return a*a; }
int n;
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); }
Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
double operator*(const Point &B)const{ return x*B.y-y*B.x; }
}O[maxn];
double r[maxn];
vector<pair<double,double> >p[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&r[i],&O[i].x,&O[i].y);
for(int j=1;j<i;j++){
double dist = sqrt(sqr(O[i].x-O[j].x)+sqr(O[i].y-O[j].y));
if(r[j]+dist<=r[i])
p[j].push_back(make_pair(-Pi,Pi));
else if(r[i]+r[j]>=dist && r[i]+dist>=r[j]){
double A = r[i], B = r[j] , C = dist;
double theta = acos((B*B+C*C-A*A)/(2*B*C)) , alpha = atan2(O[i].y-O[j].y,O[i].x-O[j].x);
double l = alpha - theta , r = alpha + theta;
if(l<-Pi) l+=2*Pi,r+=2*Pi;
if(r>Pi) p[j].push_back(make_pair(l,Pi)),p[j].push_back(make_pair(-Pi,r-2*Pi));
else p[j].push_back(make_pair(l,r));
}
}
}
double ans = 0;
for(int i=1;i<=n;i++)
{
sort(p[i].begin(),p[i].end());
int sz= p[i].size();
double mx = -inf , sum = 2*Pi;
for(int j=0;j<sz;j++){
if(mx < p[i][j].first){
mx = p[i][j].second;
sum -= mx - p[i][j].first;
}
else{
if(p[i][j].second > mx){
sum -=p[i][j].second - mx;
mx = p[i][j].second;
}
}
}
ans += sum * r[i];
}
printf("%.3lf\n",ans);
}