码迷,mamicode.com
首页 > 其他好文 > 详细

[ZJOI2008]瞭望塔

时间:2018-01-13 20:57:16      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:tps   cstring   输入格式   小数   高度   pre   输出   带来   i++   

题目描述

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

我们将H村抽象为一维的轮廓。如下图所示

技术分享图片

我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长希望建造的塔高度尽可能小。

请你写一个程序,帮助dadzhi村长计算塔的最小高度。

输入输出格式

输入格式:

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

输出格式:

输出文件tower.out仅包含一个实数,为塔的最小高度,精确到小数点后三位。

输入输出样例

输入样例#1: 复制
6
1 2 4 5 6 7
1 2 2 4 2 1
输出样例#1: 复制
1.000

说明

对于60%的数据, N ≤ 60;

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

这题分两步。第一步就是求出满足条件的半平面,这半部分就是"水平可见直线"那题。

第二部就是计算答案。可以证明瞭望塔的横坐标一定在半平面或地面的拐点处,因为中间部分一定没有其中一端优秀。

所以对半平面和地面的拐点分别拎出来讨论一下就好了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 struct Line
 8 {
 9   double k,b;
10 }line[10001],sta[10001];
11 int n,top;
12 double x[1002],y[1001],inf=1e8,eps=1e-10,ans=2e12;
13 int dcmp(double X)
14 {
15   if (X>eps) return 1;
16   if (X<-eps) return -1;
17   return 0;
18 }
19 double getx(Line a,Line b)
20 {
21   return ((b.b-a.b)/(a.k-b.k));
22 }
23 double gety(double X)
24 {int i;
25   for (i=1;i<=n;i++)
26     {
27       if (x[i+1]>=X) break;
28     }
29   if (i==n+1) return -inf;
30   double k=(y[i+1]-y[i])/(x[i+1]-x[i]),b=y[i]-k*x[i];
31   return X*k+b;
32 }
33 bool cmp(Line a,Line b)
34 {
35   if (dcmp(a.k-b.k)==0)
36     return a.b<b.b;
37   return a.k<b.k;
38 }
39 int main()
40 {
41   int i,j;
42   double maxx;
43   cin>>n;
44   for (i=1;i<=n;i++)
45     scanf("%lf",&x[i]);
46   for (i=1;i<=n;i++)
47     scanf("%lf",&y[i]);
48   for (i=1;i<=n-1;i++)
49     {
50       line[i].k=(y[i+1]-y[i])/(x[i+1]-x[i]);
51       line[i].b=y[i]-line[i].k*x[i];
52     }
53   n--;
54   sort(line+1,line+n+1,cmp);
55   line[n+1].k=inf;
56   sta[1]=line[1];sta[2]=line[2];
57   top=2;
58   for (i=3;i<=n;i++)
59     {
60       if (dcmp(line[i].k-line[i+1].k)==0)
61     continue;
62       while (top>1&&getx(line[i],sta[top-1])<=getx(sta[top],sta[top-1])) top--;
63       top++;
64       sta[top]=line[i];
65     }
66   for (i=1;i<top;i++)
67     {
68       double X=getx(sta[i],sta[i+1]);
69       double Y=sta[i].k*X+sta[i].b;
70       if (dcmp(Y-gety(X))>=0)
71       ans=min(ans,Y-gety(X));
72     }
73   for (i=1;i<=n+1;i++)
74     {
75       maxx=0;
76       for (j=1;j<=top;j++)
77     {
78       maxx=max(maxx,x[i]*sta[j].k+sta[j].b);
79     }
80       if (dcmp(maxx-y[i])>=0)
81       ans=min(ans,maxx-y[i]);
82     }
83   printf("%.3lf\n",ans);
84 }

 

[ZJOI2008]瞭望塔

标签:tps   cstring   输入格式   小数   高度   pre   输出   带来   i++   

原文地址:https://www.cnblogs.com/Y-E-T-I/p/8280248.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!