poj1819Disks

时间:2024-11-23 16:34:32

链接

题意:从左到右按顺序给你n个圆的半径,把左右两边想象成两堵墙的话,就是左右两边向里挤压,问哪些圆是对最后的宽度不影响。

刚开始理解错了,。。以为怎么放圆使宽度最小。。

这样就可以尽量使每个圆向左靠,找出当前圆与最左相切的圆,他们之间的那些圆肯定就是可以消除的,特判一下最左和最右就可以了。

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 1010
#define LL long long
#define INF 0xfffffff
const double eps = 1e-;
const double pi = acos(-1.0);
const double inf = ~0u>>;
struct point
{
double x,y,r;
point(double x=,double y=,double r =):x(x),y(y),r(r){}
}p[N];
int o[N];
bool f[N];
typedef point pointt;
pointt operator -(point a,point b)
{
return point(a.x-b.x,a.y-b.y);
}
int dcmp(double x)
{
if(fabs(x)<eps) return ;
return x<?-:;
}
double dis(point a)
{
return sqrt(a.x*a.x+a.y*a.y);
}
int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
memset(f,,sizeof(f));
for(i = ; i <= n; i++)
scanf("%lf",&p[i].r);
p[] = point(p[].r,,p[].r);
p[].r = p[].x = ;
double rig;
for(i = ; i <= n; i++)
{
double maxz = ;
int x = i-;
for(j = i- ; j >= ; j--)
{
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;
if(dcmp(d-maxz)>=)
{
maxz = max(maxz,d);
x = j;
}
}
if(dcmp(maxz-p[i].r)<=)
{
p[i].x = p[i].r;
for(j = ; j < i; j++)
f[j] = ;
continue;
}
p[i].x = maxz;
//cout<<i<<" "<<x<<" "<<maxz<<endl;
for(j = x+ ; j < i; j++)
f[j] = ;
}
int x = n;
for(i = ; i <= n ;i ++)
{
if(dcmp(p[i].r+p[i].x-rig)>)
{
rig = max(rig,p[i].r+p[i].x);
x = i;
}
}
for(i = x+ ; i <= n ;i++)
f[i] = ;
int g = ;
for(i = ; i <= n ;i++)
if(f[i])
o[++g] = i;
cout<<g<<endl;
for(i = ; i <= g ;i++)
cout<<o[i]<<endl;
}
return ;
}

相关文章