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
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
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 }