0
点赞
收藏
分享

微信扫一扫

bzoj 1038 [ZJOI2008]瞭望塔


1038: [ZJOI2008]瞭望塔


Time Limit: 10 Sec   Memory Limit: 162 MB

Submit: 2438  

Solved: 1004

[Submit][Status][Discuss]


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


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


Source



【分析】

根据轮廓线造出来一个下凸壳,然后大力观察得出答案一定是由顶点贡献得到的。(都是一次函数嘛)




【代码】

//bzoj 1038 [ZJOI2008]瞭望塔
 #include<cmath>
 #include<cstdio>
 #include<cstring>
 #include<iostream>
 #include<algorithm>
 #define eps 1e-8
 #define inf 1e10
 #define fo(i,j,k) for(i=j;i<=k;i++)
 using namespace std;
 const int mxn=305;
 int n,cnt,top;
 double ans=inf;
 struct point {double x,y;} p[mxn],t[mxn];
 struct line {double k,b;int id;} l[mxn],s[mxn];
 inline bool comp1(line l1,line l2)
 {
     if(fabs(l1.k-l2.k)<=eps) return l1.b<l2.b;
     return l1.k<l2.k;
 }
 inline bool comp2(line l1,line l2) {return l1.id<l2.id;} 
 inline void addline(int id,double x1,double y1,double x2,double y2)
 {
     l[++cnt].id=id;
     l[cnt].k=(y2-y1)/(x2-x1);
     l[cnt].b=y1-x1*(y2-y1)/(x2-x1);
 }
 inline point get(line l1,line l2)
 {
     return (point){(l2.b-l1.b)/(l1.k-l2.k),l1.k*(l2.b-l1.b)/(l1.k-l2.k)+l1.b}; 
 }
 int main()
 {
     int i,j;
     scanf("%d",&n);
     fo(i,1,n) scanf("%lf",&p[i].x);
     fo(i,1,n) scanf("%lf",&p[i].y);
     fo(i,1,n-1) addline(i,p[i].x,p[i].y,p[i+1].x,p[i+1].y);
     sort(l+1,l+n,comp1);cnt=0;
     fo(i,1,n-1)
     {
         while(top && fabs(l[i].k-s[top].k)<=eps) top--;
         while(top>1 && get(l[i],s[top]).x<=get(s[top],s[top-1]).x) top--;
         s[++top]=l[i];
     }
     sort(l+1,l+n,comp2);
     fo(i,1,top-1)
     {
         point P=get(s[i],s[i+1]);
         fo(j,1,n-1)
           if(P.x>=p[j].x && P.x<=p[j+1].x)
           {
              ans=min(ans,P.y-(l[j].k*P.x+l[j].b));
              break;
     }
     }
     fo(i,1,n)
     {
         point P=p[i];
         fo(j,1,top)
         {
             point p1=get(s[j-1],s[j]),p2=get(s[j],s[j+1]);
             if(j==1) p1.x=-inf;
             if(j==top) p2.x=inf;
             if(P.x>=p1.x && P.x<=p2.x)
             {
              ans=min(ans,s[j].k*P.x+s[j].b-P.y);
              break;
    }
         }
     }
     printf("%.3lf\n",ans);
     return 0;
 }
 /*
 Best day of my life.
 */


举报

相关推荐

0 条评论