P5 UVA1308 Viva Confetti
这道题主要是去理解所谓的 "看得见" 的面积是怎么组成的。
对于每个露出来的面积,其实是由多个圆弧所组成的。是的,这就是为什么要以圆弧为引入点来解决此题的原因。
那该怎么找露出来的面积呢?题目有说,在一定范围内不影响答案,所以考虑找每个圆弧的中点,然后平移一点点距离,再从覆盖顺序看最上层盖住这个点的圆是谁,如果有盖住此点的圆,就说明这个圆是露出来的。
const int N=100;
int n;
Circle C[N];
bool tag[N];
inline int topmost(Point P){
for(int i=n-1;i>=0;--i)
if(dcmp(Length(C[i].c-P)-C[i].r)<0)
return i;
return -1;
}
signed main(){
IOS
while(cin>>n){
if(!n) break;
for(int i=0;i<n;++i)
cin>>C[i].c.x>>C[i].c.y>>C[i].r;
memset(tag,0,sizeof(tag));
for(int i=0;i<n;++i){
vector<double> rad;
rad.push_back(0),rad.push_back(PI*2);
for(int j=0;j<n;++j) GetCircleCircleIntersection(C[i],C[j],rad);//圆与圆交点(略)
sort(All(rad));
for(int j=0;j<rad.size()-1;++j){
double mid=(rad[j]+rad[j+1])/2.0;
for(int t=-1;t<=1;t+=2){
double r2=C[i].r+t*eps;
Circle K=C[i]; K.r=r2;//新圆
Point pos=K.GetPoint(mid);//圆弧中点
int jd=topmost(pos);
if(jd>=0) tag[jd]=true;
}
}
}
int ans=0;
for(int i=0;i<n;++i) ans+=tag[i];
cout<<ans<<'\n';
}
return 0;
}
·EOF