标签:style class blog http get 表
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4562
题意:给出一个点p(X,Y)以及若干圆。从中选出尽可能多的圆满足:圆能且只能包含p或者原点中的一个(不能在圆上);圆之间不能相交或者相切。
思路:首先分理出只包含原点或者p的圆,然 后分别按照半径升序排序。分别对包含原点和p的进行dp。f1[i]表示包含原点的圆中前i个最多选出多少个。f2[i]表示p的。然后合并。就是枚举 f1的i和f2的j,若这两个圆不冲突,那么就能选出f1[i]+f2[j]个。
const int N=1005; class point { public: int x,y; point(){} point(int _x,int _y) { x=_x; y=_y; } void get() { RD(x,y); } point operator-(point a) { return point(x-a.x,y-a.y); } int len() { return x*x+y*y; } }; class Circle { public: point p; int R; void get() { p.get(); RD(R); } int on(point a) { return R*R==(a-p).len(); } int in(point a) { return R*R>(a-p).len(); } int ok(Circle a) { int x=abs(a.R-R),y=a.R+R,L=(a.p-p).len(); return L<x*x||L>y*y; } }; point a,b; vector<Circle> p,q; int n,f1[N],f2[N]; int cmp(Circle a,Circle b) { return a.R<b.R; } int DP() { sort(p.begin(),p.end(),cmp); sort(q.begin(),q.end(),cmp); int ans=0,i,j; FOR0(i,SZ(p)) { f1[i]=0; FOR0(j,i) if(p[i].ok(p[j])) f1[i]=max(f1[i],f1[j]); f1[i]++; ans=max(ans,f1[i]); } FOR0(i,SZ(q)) { f2[i]=0; FOR0(j,i) if(q[i].ok(q[j])) f2[i]=max(f2[i],f2[j]); f2[i]++; ans=max(ans,f2[i]); } FOR0(i,SZ(p)) FOR0(j,SZ(q)) if(p[i].ok(q[j])) { ans=max(ans,f1[i]+f2[j]); } return ans; } int main() { int num=0; rush() { RD(n); b.get(); a=point(0,0); Circle t; int i; p.clear(); q.clear(); FOR0(i,n) { t.get(); if(t.on(a)||t.on(b)) continue; if(t.in(a)&&!t.in(b)) p.pb(t); if(!t.in(a)&&t.in(b)) q.pb(t); } printf("Case %d: ",++num); PR(DP()); } }
标签:style class blog http get 表
原文地址:http://www.cnblogs.com/jianglangcaijin/p/3799551.html