zoukankan      html  css  js  c++  java
  • 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

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

    正解:半平面交。

    题目给了你一个半平面交,还要求一个半平面交。求出两个半平面交以后,直接抽象到坐标系上,对于两个分段函数,它们的距离最小值所在的位置只可能出现在两个函数的任意一个端点上。所以枚举每个端点,计算垂直距离,求出最小值就行了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf 1e18
    14 #define eps 1e-9
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18  
    19 using namespace std;
    20  
    21 struct node{ double a,b; }l[100010],st[100010];
    22 struct point{ double x,y; }a[100010];
    23  
    24 double ans;
    25 int n,num;
    26  
    27 il int gi(){
    28     RG int x=0,q=0; RG char ch=getchar();
    29     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar();
    30     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x;
    31 }
    32  
    33 il int cmp(const node &l1,const node &l2){ if (abs(l1.a-l2.a)<eps) return l1.b<l2.b; return l1.a<l2.a; }
    34  
    35 il double getx(RG node x,RG node y){ return (x.b-y.b)/(y.a-x.a); }
    36  
    37 il double gety(RG double x){
    38     RG int i; for (i=1;i<=n+1;++i) if (i==n+1 || a[i+1].x>=x) break; if (i==n+1) return -inf;
    39     RG double A=(a[i+1].y-a[i].y)/(a[i+1].x-a[i].x),B=a[i].y-A*a[i].x; return A*x+B;
    40 }
    41  
    42 il double gy(RG double x){ RG double ans=0; for (RG int i=1;i<=num;++i) ans=max(ans,st[i].a*x+st[i].b); return ans; }
    43  
    44 il void work(){
    45     n=gi()-1; for (RG int i=1;i<=n+1;++i) scanf("%lf",&a[i].x); for (RG int i=1;i<=n+1;++i) scanf("%lf",&a[i].y);
    46     for (RG int i=1;i<=n;++i) l[i].a=(a[i+1].y-a[i].y)/(a[i+1].x-a[i].x),l[i].b=a[i].y-l[i].a*a[i].x;
    47     sort(l+1,l+n+1,cmp); l[n+1].a=inf,ans=inf;
    48     for (RG int i=1;i<=n;++i){
    49     if (abs(l[i+1].a-l[i].a)<eps) continue; if (num<=1){ st[++num]=l[i]; continue; }
    50     while(num>=2 && getx(l[i],st[num])<getx(st[num],st[num-1])) num--; st[++num]=l[i];
    51     }
    52     for (RG int i=1;i<num;++i){ RG double x=getx(st[i],st[i+1]),y=st[i].a*x+st[i].b,Y=gety(x); ans=min(ans,y-Y); }
    53     for (RG int i=1;i<=n+1;++i) ans=min(ans,gy(a[i].x)-a[i].y); printf("%0.3lf",ans); return;
    54 }
    55  
    56 int main(){
    57     work();
    58     return 0;
    59 }
  • 相关阅读:
    00:Java简单了解
    QQ空间相册照片批量导出
    Git基本操作
    【有钱的大佬看过来】Java开发学习大纲
    默认端口号走一波
    获取“今日头条”西瓜视频
    CentOS 下源码安装LAMP环境
    书写是为了更好的思考
    U盘安装Ubuntu 14.04 LTS正式版 出现如下的提示,不能继续,如何操作?
    U盘安装Ubuntu 14.04 LTS正式版
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6416568.html
Copyright © 2011-2022 走看看