1038: [ZJOI2008]瞭望塔 - BZOJ

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
【数据规模】
对于60%的数据, N ≤ 60;
对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。

 

其实这个范围是可以乱搞的,我O(n^2)乱搞,结果各种细节没注意

首先从别人那里知道了塔的横坐标要么是凸壳上的顶点的横坐标,要么是地图拐点的横坐标

所以只要求出来这些横坐标就行

主要是求凸壳上的顶点

我们枚举一条线与其他线的交点(只与斜率比它大的线做交点,然后取横坐标最小的,这样就不重不漏),但是这个不一定是凸包上的,所以还要判断一下

 1 const
 2     maxn=310;
 3     inf=9999999999999999;
 4     eps=1e-7;
 5 type
 6     node=record
 7       x,y:double;
 8     end;
 9 var
10     a,b,c:array[0..maxn]of node;
11     ans:double;
12     n:longint;
13 
14 function min(x,y:double):double;
15 begin
16     if x<y then exit(x);
17     exit(y);
18 end;
19 
20 function max(x,y:double):double;
21 begin
22     if x>y then exit(x);
23     exit(y);
24 end;
25 
26 procedure init;
27 var
28     i,j:longint;
29     y:double;
30     flag:boolean;
31 begin
32     read(n);
33     for i:=1 to n do
34       read(a[i].x);
35     for i:=1 to n do
36       read(a[i].y);
37     for i:=1 to n-1 do
38       begin
39         b[i].x:=(a[i].y-a[i+1].y)/(a[i].x-a[i+1].x);
40         b[i].y:=a[i].y-a[i].x*b[i].x;
41       end;
42     ans:=inf;
43     for i:=1 to n do
44       begin
45         y:=a[i].y;
46         for j:=1 to n-1 do
47           y:=max(y,a[i].x*b[j].x+b[j].y);
48         ans:=min(ans,y-a[i].y);
49       end;
50     c:=a;
51     for i:=1 to n-1 do
52       begin
53         for j:=1 to n-1 do
54           if b[i].x+eps<b[j].x then
55           begin
56             a[i].x:=(b[j].y-b[i].y)/(b[i].x-b[j].x);
57             a[i].y:=a[i].x*b[i].x+b[i].y;
58             break;
59           end;
60         for j:=1 to n-1 do
61           if b[i].x+eps<b[j].x then
62           if (b[j].y-b[i].y)/(b[i].x-b[j].x)<a[i].x then
63           begin
64             a[i].x:=(b[j].y-b[i].y)/(b[i].x-b[j].x);
65             a[i].y:=a[i].x*b[i].x+b[i].y;
66           end;
67       end;
68     for i:=1 to n-1 do
69       begin
70         flag:=true;
71         for j:=1 to n-1 do
72           if a[i].y+eps<a[i].x*b[j].x+b[j].y then flag:=false;
73         if flag=false then continue;
74         for j:=1 to n-1 do
75           if (c[j].x-eps<a[i].x) and (a[i].x<c[j+1].x+eps) then ans:=min(ans,a[i].y-a[i].x*b[j].x-b[j].y);
76       end;
77     write(ans+eps:0:3);
78 end;
79 
80 begin
81     init;
82 end.
View Code

 

posted @ 2014-04-01 17:26  Randolph87  阅读(330)  评论(0)    收藏  举报