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

 

你可能感兴趣的:(2008)