首页 > 代码库 > poj1819Disks
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 101012 #define LL long long13 #define INF 0xfffffff14 const double eps = 1e-8;15 const double pi = acos(-1.0);16 const double inf = ~0u>>2;17 struct point18 {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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。