2201:Immortal Jewels
問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2201
金属棒の候補となる直線は
2円の共通内・外接線
2円の内一方の半径にmを足したものと他方の円の共通内・外接線
両方の半径にmを足したものの共通内・外接線
の3通り。これを全列挙して個数を数える。
のはずだが、自分のコードは3つ目の両方にmを足すパターンを試さなくても通ってしまっている。
#include<iostream> #include<vector> #include<algorithm> #include<cmath> #define all(c) (c).begin(),(c).end() using namespace std; typedef double Real; Real EPS = 1e-8; const Real PI = acos(-1); int sgn(Real a, Real b=0){return a<b-EPS?-1:a>b+EPS?1:0;} Real sqr(Real a){return sqrt(max(a,(Real)0));} struct Point{ Real add(Real a, Real b){ if(abs(a+b) < EPS*(abs(a)+abs(b)))return 0; return a+b; } Real x, y; Point(){} Point(Real x,Real y) : x(x) , y(y){} Point operator + (Point p){return Point(add(x,p.x), add(y,p.y));} Point operator - (Point p){return Point(add(x,-p.x), add(y,-p.y));} Point operator * (Real d){return Point(x*d,y*d);} Real norm(){return sqr(x*x+y*y);} Real dot(Point a){return x*a.x+y*a.y;} Real cross(Point a){return x*a.y-y*a.x;} Real arg(){ if(sgn(x)>0)return atan(y/x); if(sgn(x)<0)return atan(y/x)+PI; if(sgn(y)>0)return PI/2; if(sgn(y)<0)return 3*PI/2; return 0; } }; struct Line{ Point a,b; Line(){} Line(Point a,Point b):a(a),b(b){} Real dist(Point c){return abs((b-a).cross(c-a))/(b-a).norm();} }; struct Circle{ Point p; Real r; Circle(){} Circle(Point p, Real r) : p(p) , r(r){} Line tangent(Real theta){ Point a(r*cos(theta),r*sin(theta)); Point b(a.y,-a.x); return Line(p+a,p+a+b); } vector<Line> commonTangent(Circle x){ vector<Line>res; x.p=x.p-p; Real a=x.p.arg(); Real b[2]={(r-x.r),(r+x.r)}; for(int i=0;i<2;i++){ b[i]/=x.p.norm(); if(sgn(b[i],-1.0)<0 || sgn(b[i],1.0)>0)return res; Real c=asin(b[i])-asin(1.0); res.push_back(tangent(a-c)); res.push_back(tangent(a+c)); } return res; } }; int n; vector<Circle>c; vector<Real>m; vector<Line> enumerate(){ vector<Line>res; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==j)continue; vector<Line>tmp=c[i].commonTangent(c[j]); for(int k=0;k<tmp.size();k++){ res.push_back(tmp[k]); } c[i].r+=m[i]; tmp=c[i].commonTangent(c[j]); for(int k=0;k<tmp.size();k++){ res.push_back(tmp[k]); } c[i].r-=m[i]; } } return res; } int count(Line l){ int cnt=0; for(int i=0;i<n;i++){ Real d=l.dist(c[i].p)-c[i].r; cnt+=(sgn(d)>=0 && sgn(d,m[i])<=0); } return cnt; } int main(void){ while(cin >> n,n){ c.resize(n); m.resize(n); for(int i=0;i<n;i++) cin >> c[i].p.x >> c[i].p.y >> c[i].r >> m[i]; vector<Line>res=enumerate(); int cnt=0; for(int i=0;i<res.size();i++){ cnt=max(cnt,count(res[i])); } cout << max(1,cnt) << endl; } return 0; }