bzoj1038: [ZJOI2008]瞭望塔

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

 

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

 
题解:
http://blog.csdn.net/popoqqq/article/details/39340759
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 char ch;
 8 bool ok;
 9 void read(int &x){
10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
12     if (ok) x=-x;
13 }
14 void read(double &x){
15     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
16     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
17     if (ok) x=-x;
18 }
19 const int maxn=305;
20 const double eps=1E-8;
21 int n;
22 double x[maxn],y[maxn],l,m,r,lim;
23 double getrand(){return rand()%1000000/1000000.0;}
24 double cross(double x,double y,double xx,double yy){return x*yy-xx*y;}
25 bool check(double pos,double h){
26     for (int i=2;i<=n;i++) if (cross(x[i-1]-pos,y[i-1]-h,x[i]-pos,y[i]-h)<0) return false;
27     return true;
28 }
29 double get_h(double pos){
30     for (int i=2;i<=n;i++) if (x[i-1]<=pos&&pos<=x[i]) return y[i-1]+(y[i]-y[i-1])/(x[i]-x[i-1])*(pos-x[i-1]);
31     return -1E12;
32 }
33 double calc(double pos){
34     l=get_h(pos),r=1E12;
35     while (r-l>eps){
36         m=(l+r)/2;
37         if (check(pos,m)) r=m; else l=m;
38     }
39     return l-get_h(pos);
40 }
41 void sa(){
42     double now=x[1]+getrand()*lim,nxt,t1=calc(now),t2;
43     for (double T=lim;T>0.000001;T*=0.996){
44         double dx=T*(getrand()*2-1);
45         nxt=now+dx;        
46         t2=calc(nxt);
47         if (exp((t1-t2)/T)>getrand()) now=nxt,t1=t2;
48     }
49     printf("%.3lf\n",t1);
50 }
51 int main(){
52     srand(19990617);
53     read(n);
54     for (int i=1;i<=n;i++) read(x[i]);
55     for (int i=1;i<=n;i++) read(y[i]);
56     lim=x[n]-x[1],sa();
57     return 0;
58 }

 

posted @ 2016-03-12 09:19  chenyushuo  阅读(276)  评论(0编辑  收藏  举报