poj1819Disks
题意:从左到右按顺序给你n个圆的半径,把左右两边想象成两堵墙的话,就是左右两边向里挤压,问哪些圆是对最后的宽度不影响。
刚开始理解错了,。。以为怎么放圆使宽度最小。。
这样就可以尽量使每个圆向左靠,找出当前圆与最左相切的圆,他们之间的那些圆肯定就是可以消除的,特判一下最左和最右就可以了。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 1010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 struct point 18 { 19 double x,y,r; 20 point(double x=0,double y=0,double r =0):x(x),y(y),r(r){} 21 }p[N]; 22 int o[N]; 23 bool f[N]; 24 typedef point pointt; 25 pointt operator -(point a,point b) 26 { 27 return point(a.x-b.x,a.y-b.y); 28 } 29 int dcmp(double x) 30 { 31 if(fabs(x)<eps) return 0; 32 return x<0?-1:1; 33 } 34 double dis(point a) 35 { 36 return sqrt(a.x*a.x+a.y*a.y); 37 } 38 int main() 39 { 40 int n,i,j; 41 while(scanf("%d",&n)!=EOF) 42 { 43 memset(f,0,sizeof(f)); 44 for(i = 1; i <= n; i++) 45 scanf("%lf",&p[i].r); 46 p[1] = point(p[1].r,0,p[1].r); 47 p[0].r = p[0].x = 0; 48 double rig; 49 for(i = 2; i <= n; i++) 50 { 51 double maxz = 0; 52 int x = i-1; 53 for(j = i-1 ; j >= 1 ; j--) 54 { 55 double d = sqrt((p[j].r+p[i].r)*(p[j].r+p[i].r)-(p[j].r-p[i].r)*(p[j].r-p[i].r))+p[j].x; 56 if(dcmp(d-maxz)>=0) 57 { 58 maxz = max(maxz,d); 59 x = j; 60 } 61 } 62 if(dcmp(maxz-p[i].r)<=0) 63 { 64 p[i].x = p[i].r; 65 for(j = 1 ; j < i; j++) 66 f[j] = 1; 67 continue; 68 } 69 p[i].x = maxz; 70 //cout<<i<<" "<<x<<" "<<maxz<<endl; 71 for(j = x+1 ; j < i; j++) 72 f[j] = 1; 73 } 74 int x = n; 75 for(i = 1; i <= n ;i ++) 76 { 77 if(dcmp(p[i].r+p[i].x-rig)>0) 78 { 79 rig = max(rig,p[i].r+p[i].x); 80 x = i; 81 } 82 } 83 for(i = x+1 ; i <= n ;i++) 84 f[i] = 1; 85 int g = 0; 86 for(i = 1; i <= n ;i++) 87 if(f[i]) 88 o[++g] = i; 89 cout<<g<<endl; 90 for(i = 1; i <= g ;i++) 91 cout<<o[i]<<endl; 92 } 93 return 0; 94 }