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,注意考虑实数误差带来的问题。

    我们先求一个半平面交
    答案只可能出现在半平面的折点和地面上的城市折点上
    这里写图片描述

    tip

    在求直线的时候,一定要按顺序
    在用线切割的时候,只用给出的n个点组成的线切割
    只要涉及到double类型的比较,都要用dcmp
    eps=1e-10

    这里写代码片
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    
    using namespace std;
    
    const int N=100001;
    const double eps=1e-10;
    const double INF=1e10;
    struct node{
        double x,y;
        node (double xx=0,double yy=0)
        {
            x=xx;y=yy;
        }
    };
    node po[N],p[N],q[N],g[N];
    int n,m,nn;
    double a,b,c;
    
    int dcmp(double x)
    {
        if (fabs(x)<eps) return 0;
        else if (x>0) return 1;
        else return -1;
    }
    
    node operator +(const node &x,const node &y){return node(x.x+y.x,x.y+y.y);}
    node operator -(const node &x,const node &y){return node(x.x-y.x,x.y-y.y);}
    node operator *(const node &x,const double &y){return node(x.x*y,x.y*y);}
    node operator /(const node &x,const double &y){return node(x.x/y,x.y/y);}
    
    double Cross(const node x,const node y){return x.x*y.y-x.y*y.x;}
    double Dot(const node x,const node y){return x.x*y.x+x.y*y.y;}
    
    void getline(node x,node y)
    {
        a=y.y-x.y;
        b=x.x-y.x;
        c=x.y*y.x-x.x*y.y;
    }
    
    node insert(node x,node y)
    {
        double u=fabs(a*x.x+b*x.y+c);
        double v=fabs(a*y.x+b*y.y+c);
        node ans;
        ans.x=(u*y.x+v*x.x)/(u+v);
        ans.y=(u*y.y+v*x.y)/(u+v);
        return ans;
    }
    
    void cut()
    {
        int cnt=0;
        for (int i=1;i<=m;i++)
        {
            if (dcmp(a*p[i].x+b*p[i].y+c)<=0) q[++cnt]=p[i];  //直线左侧
            else
            {
                if (dcmp(a*p[i-1].x+b*p[i-1].y+c)<0) q[++cnt]=insert(p[i-1],p[i]);
                if (dcmp(a*p[i+1].x+b*p[i+1].y+c)<0) q[++cnt]=insert(p[i+1],p[i]);
            } 
        }
        for (int i=1;i<=cnt;i++) p[i]=q[i];
        p[0]=p[cnt];  p[cnt+1]=p[1];
        m=cnt;
    }
    
    void solve()
    {
        int i;
        for (i=1;i<=n;i++) p[i]=po[i];
        m=n;
        p[0]=p[n]; p[n+1]=p[1]; po[0]=po[n]; po[n+1]=po[1];
        for (int i=2;i<=nn;i++)   //<=nn
        {
            getline(po[i-1],po[i]);
            cut();
        }
    }
    
    void doit()
    {
        int i,j,k;
        double ans=1e60;
        g[nn+1]=g[1]; g[0]=g[nn];
        for (i=1;i<=nn;i++)
            for (j=1;j<=m;j++)
                if (dcmp(p[j].x-g[i].x)<=0&&dcmp(p[j+1].x-g[i].x)>=0)
                {
                    getline(p[j],p[j+1]);
                    double yy=(a*g[i].x+c)/(-b);
                    yy=abs(yy-g[i].y);
                    if (dcmp(ans-yy)>0) ans=yy;
                }
        for (i=1;i<=m;i++)
            for (j=1;j<=nn;j++)
                if (dcmp(g[j].x-p[i].x)<=0&&dcmp(g[j+1].x-p[i].x)>=0)
                {
                    getline(g[j],g[j+1]);
                    double yy=(a*p[i].x+c)/(-b);
                    yy=abs(yy-p[i].y);
                    if (dcmp(ans-yy)>0) ans=yy;
                }
        printf("%0.3lf",ans);
    }
    
    int main()
    {
        scanf("%d",&n); nn=n;
        if (n==1){printf("0.000");return 0;}
        for (int i=1;i<=n;i++) scanf("%lf",&po[i].x),g[i].x=po[i].x;
        for (int i=1;i<=n;i++) scanf("%lf",&po[i].y),g[i].y=po[i].y;
        po[++n].x=INF; po[n].y=-INF;   //逆时针
        po[++n].x=INF; po[n].y=INF;
        po[++n].x=-INF; po[n].y=INF;
        po[++n].x=-INF; po[n].y=-INF;
        solve();
        doit();
        return 0;
    }
  • 相关阅读:
    java后端工具积累
    Java基础面试题整理
    MySql常问面试题
    jvm及并发面试题
    中间件redis kafka面试题
    笔记
    解决Git操作报错
    view的state和drawable的state 源码分析
    flutter_6_动态化简介
    有关namespace 命名空间
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673296.html
Copyright © 2011-2022 走看看