1132:Circle and Points
xy平面上にN個の点が与えられるので、半径1の円を動かして
囲むことができる点の個数の最大値を求める問題。
2つの点を円周上にもつ円が最大値の候補になる。
N個の点の中から2点を決めて、その2点を円周上にもつ円を挙げ
囲まれている点の数を数えた。
2点を円周上に持つ円の計算は、
http://homepage1.nifty.com/gfk/circle-circle.htm
を参考にして作った2円の交点座標を求める関数があったので
選んだ2点を中心とした、半径1の円同士の交点を中心とする2円とした。
#include<iostream> #include<cmath> #include<vector> #include<algorithm> using namespace std; double EPS=1e-10; double add(double a,double b){ if(abs(a+b)<EPS * (abs(a)+abs(b)))return 0; return a+b; } struct point{ double x,y; point(){} point(double x,double 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 * (double d) { return point(x*d,y*d); } point operator / (double d) { return point(x/d,y/d); } bool operator == (const point &p)const{ return abs(x-p.x)<EPS && abs(y-p.y)<EPS; } }; struct circle{ point p; double r; circle(){} circle(point p,double r):p(p),r(r){} }; double dist(point a, point b){ return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)); } vector<point> circle_cross_point(circle a, circle b){ vector<point>ret; double x=a.p.x-b.p.x,y=a.p.y-b.p.y; double L=x*x+y*y; if(L>pow(a.r+b.r,2))return ret; L=sqrt(L); double C=atan2(b.p.y-a.p.y,b.p.x-a.p.x); double alpha=acos((L*L+a.r*a.r-b.r*b.r)/(2*L*a.r)); point r1,r2; r1.x=a.p.x+cos(C+alpha),r1.y=a.p.y+sin(C+alpha); r2.x=a.p.x+cos(C-alpha),r2.y=a.p.y+sin(C-alpha); ret.push_back(r1),ret.push_back(r2); return ret; } int main(void){ int n; point a; vector<point>P; vector<circle>C; while(cin >> n,n){ P.clear(); C.clear(); for(int i=0;i<n;i++){ cin >> a.x >> a.y; P.push_back(a); } for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ if(dist(P[i],P[j])>2.0+EPS)continue; vector<point>res=circle_cross_point(circle(P[i],1.0),circle(P[j],1.0)); for(int k=0;k<res.size();k++) C.push_back(circle(res[k],1)); } } int ans=1; for(int i=0;i<C.size();i++){ int cnt=0; for(int j=0;j<P.size();j++) if(dist(C[i].p,P[j])<1.0+EPS)cnt++; ans=max(ans,cnt); } cout << ans << endl; } return 0; }