链接:
#include <stdio.h>
int main()
{
puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/46564199");
}
题解:
给每个圆求一下:
1. 它是不是被之后的某圆整体覆盖。
2. 它的圆周上有哪些弧段被覆盖了。
然后对于每个圆求一下还剩多少周长即可。
上述的“2.”可以用圆的圆心角区间来表示哪些弧段被覆盖。
然后圆心角大小可以用余弦定理求,位置可以取两圆心连线的角度加减其圆心角的一半。
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
#define eps 1e-7
using namespace std;
const double pi=acos(-1.0);
struct Point
{
double x,y;
void read(){scanf("%lf%lf",&x,&y);}
double operator - (const Point &A)const
{return sqrt((x-A.x)*(x-A.x)+(y-A.y)*(y-A.y));}
};
struct Circle
{
Point c;
double r;
void read()
{
scanf("%lf",&r);
c.read();
}
}c[N]; // circles
int cnt[N],n;
struct Segment
{
double l,r;
Segment(double _l=0,double _r=0):l(_l),r(_r){}
bool keep()
{
if(r>pi)
{
r-=2*pi;
return 1;
}
if(l<-pi)
{
l+=2*pi;
return 1;
}
return 0;
}
bool operator < (const Segment &A)const
{return l<A.l;}
}seg[N][N<<1],sg;
int inc(const Circle &A,const Circle &B) // 判断半径和圆心距离
{
double dis=A.c-B.c;
if(A.r+B.r<dis)return 0;
if(A.r+eps>B.r&&A.r-B.r+eps>dis)return -1;
if(B.r+eps>A.r&&B.r-A.r+eps>dis)return 0;
return 1;
}
void getinc(const Circle &A,const Circle &B,double &ret1,double &ret2)
{
double angle=atan2(B.c.y-A.c.y,B.c.x-A.c.x),dis=A.c-B.c;
double dang=acos((B.r*B.r+dis*dis-A.r*A.r)/(2*dis*B.r));
ret1=angle-dang,ret2=angle+dang;
}
bool die[N];
double ans;
int main()
{
// freopen("test.in","r",stdin);
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
c[i].read();
for(j=1;j<i;j++)if(!die[j])if(k=inc(c[i],c[j]))
{
if(k==-1)
{
die[j]=true;
continue;
}
cnt[j]++;
getinc(c[i],c[j],seg[j][cnt[j]].l,seg[j][cnt[j]].r);
if(seg[j][cnt[j]].keep())
{
cnt[j]++;
seg[j][cnt[j]]=Segment(-pi,seg[j][cnt[j]-1].r);
seg[j][cnt[j]-1].r=pi;
}
}
}
double remain;
for(i=1;i<=n;i++)if(!die[i])
{
sort(seg[i]+1,seg[i]+cnt[i]+1);
remain=2*pi,sg.l=sg.r=-remain;
for(j=1;j<=cnt[i];j++)
{
if(seg[i][j].l>sg.r)
{
remain-=(sg.r-sg.l);
sg=seg[i][j];
}
else sg.r=max(sg.r,seg[i][j].r);
}
remain-=(sg.r-sg.l);
// ans+=2*pi*c[i].r*remain/(2*pi);
ans+=c[i].r*remain;
}
printf("%.3lf\n",ans);
return 0;
}
时间: 2024-12-17 17:43:34