P5 UVA1308 Viva Confetti

发布时间 2023-08-20 09:42:14作者: Michael·F·Chen

这道题主要是去理解所谓的 "看得见" 的面积是怎么组成的。

对于每个露出来的面积,其实是由多个圆弧所组成的。是的,这就是为什么要以圆弧为引入点来解决此题的原因。

那该怎么找露出来的面积呢?题目有说,在一定范围内不影响答案,所以考虑找每个圆弧的中点,然后平移一点点距离,再从覆盖顺序看最上层盖住这个点的圆是谁,如果有盖住此点的圆,就说明这个圆是露出来的。

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;
}