AOJ : 0090 - Overlaps of Seals

アルゴリズム

max=1, で初期化.(1枚でも重なっていると考えるため)
二重ループで, 任意の二つの円を選びます.
この二つの円の交点を求め, これらの交点を内包する円をカウントします(二重ループで選んだ二つの円は除く).
このカウント数+2がmaxより大きければ更新.

プログラム

#include <iostream>
#include <complex>
#include <vector>
using namespace std;

#define EPS (1e-5)

typedef complex<double> P;

vector<P> crossPoint(P a,P b){
  vector<P> res;

  if(abs(abs(b-a) - 2.0) < EPS){
    P c = a + b;
    res.push_back( P(c.real()/2,c.imag()/2) );
  }
  else if(abs(b-a) < 2.0){
    //円と円の交点計算
    P ab = b - a; //AからBへのベクトル
    P center = a + P(ab.real()/2,ab.imag()/2); //ABの中点へのベクトル
    P un1 = (ab * P(0, +1)) / abs(ab); //abの法線ベクトル1
    P un2 = (ab * P(0, -1)) / abs(ab); //abの法線ベクトル2
    double dist = sqrt(1 - pow(abs(ab) / 2, 2)); //ABの中点から円の交点までの距離
    P c1 = center + un1 * dist; //円の交点へのベクトル1
    P c2 = center + un2 * dist; //円の交点へのベクトル2

    res.push_back(c1);
    res.push_back(c2);
  }

  return res;
}

int main(void){
  int n;

  while(cin>>n,n){
    P p[n];
    for(int i=0;i<n;i++){
      double x,y;
      char ch;
      cin>>x>>ch>>y;
      p[i] = P(x,y);
    }

    int ans = 1;
    for(int i=0;i<n;i++){
      for(int j=i+1;j<n;j++){
        vector<P> v = crossPoint(p[i],p[j]);
        if(v.empty()) continue;
        int countA = 2;
        int countB = 2;
        for(int k=0;k<n;k++){
          if(i == k || j == k) continue;
          if(abs(v[0]-p[k]) - 1.0 < EPS) countA++;
          if(v.size() == 2 && abs(v[1]-p[k]) - 1.0 < EPS) countB++;
        }
        ans = max(ans,max(countA,countB));
      }
    }
    cout<<ans<<endl;
  }

  return 0;
}