您的位置:首页 > 其它

bzoj1038 [ZJOI2008]瞭望塔

2017-09-06 20:03 281 查看
Description

  致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。我们

将H村抽象为一维的轮廓。如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描

述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可

以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长

希望建造的塔高度尽可能小。请你写一个程序,帮助dadzhi村长计算塔的最小高度。

Input

  第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1

~ yn。

Output

  仅包含一个实数,为塔的最小高度,精确到小数点后三位。

Sample Input

【输入样例一】

6

1 2 4 5 6 7

1 2 2 4 2 1

【输入样例二】

4

10 20 49 59

0 10 10 0

Sample Output

【输出样例一】

1.000

【输出样例二】

14.500

HINT

N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。

我们先求一个半平面交

答案只可能出现在半平面的折点和地面上的城市折点上



tip

在求直线的时候,一定要按顺序

在用线切割的时候,只用给出的n个点组成的线切割

只要涉及到double类型的比较,都要用dcmp

eps=1e-10

这里写代码片
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>

using namespace std;

const int N=100001;
const double eps=1e-10;
const double INF=1e10;
struct node{
double x,y;
node (double xx=0,double yy=0)
{
x=xx;y=yy;
}
};
node po
,p
,q
,g
;
int n,m,nn;
double a,b,c;

int dcmp(double x)
{
if (fabs(x)<eps) return 0;
else if (x>0) return 1;
else return -1;
}

node operator +(const node &x,const node &y){return node(x.x+y.x,x.y+y.y);}
node operator -(const node &x,const node &y){return node(x.x-y.x,x.y-y.y);}
node operator *(const node &x,const double &y){return node(x.x*y,x.y*y);}
node operator /(const node &x,const double &y){return node(x.x/y,x.y/y);}

double Cross(const node x,const node y){return x.x*y.y-x.y*y.x;}
double Dot(const node x,const node y){return x.x*y.x+x.y*y.y;}

void getline(node x,node y)
{
a=y.y-x.y;
b=x.x-y.x;
c=x.y*y.x-x.x*y.y;
}

node insert(node x,node y)
{
double u=fabs(a*x.x+b*x.y+c);
double v=fabs(a*y.x+b*y.y+c);
node ans;
ans.x=(u*y.x+v*x.x)/(u+v);
ans.y=(u*y.y+v*x.y)/(u+v);
return ans;
}

void cut()
{
int cnt=0;
for (int i=1;i<=m;i++)
{
if (dcmp(a*p[i].x+b*p[i].y+c)<=0) q[++cnt]=p[i];  //直线左侧
else
{
if (dcmp(a*p[i-1].x+b*p[i-1].y+c)<0) q[++cnt]=insert(p[i-1],p[i]);
if (dcmp(a*p[i+1].x+b*p[i+1].y+c)<0) q[++cnt]=insert(p[i+1],p[i]);
}
}
for (int i=1;i<=cnt;i++) p[i]=q[i];
p[0]=p[cnt];  p[cnt+1]=p[1];
m=cnt;
}

void solve()
{
int i;
for (i=1;i<=n;i++) p[i]=po[i];
m=n;
p[0]=p
; p[n+1]=p[1]; po[0]=po
; po[n+1]=po[1];
for (int i=2;i<=nn;i++)   //<=nn
{
getline(po[i-1],po[i]);
cut();
}
}

void doit()
{
int i,j,k;
double ans=1e60;
g[nn+1]=g[1]; g[0]=g[nn];
for (i=1;i<=nn;i++)
for (j=1;j<=m;j++)
if (dcmp(p[j].x-g[i].x)<=0&&dcmp(p[j+1].x-g[i].x)>=0)
{
getline(p[j],p[j+1]);
double yy=(a*g[i].x+c)/(-b);
yy=abs(yy-g[i].y);
if (dcmp(ans-yy)>0) ans=yy;
}
for (i=1;i<=m;i++)
for (j=1;j<=nn;j++)
if (dcmp(g[j].x-p[i].x)<=0&&dcmp(g[j+1].x-p[i].x)>=0)
{
getline(g[j],g[j+1]);
double yy=(a*p[i].x+c)/(-b);
yy=abs(yy-p[i].y);
if (dcmp(ans-yy)>0) ans=yy;
}
printf("%0.3lf",ans);
}

int main()
{
scanf("%d",&n); nn=n;
if (n==1){printf("0.000");return 0;}
for (int i=1;i<=n;i++) scanf("%lf",&po[i].x),g[i].x=po[i].x;
for (int i=1;i<=n;i++) scanf("%lf",&po[i].y),g[i].y=po[i].y;
po[++n].x=INF; po
.y=-INF;   //逆时针
po[++n].x=INF; po
.y=INF;
po[++n].x=-INF; po
.y=INF;
po[++n].x=-INF; po
.y=-INF;
solve();
doit();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: