• HDU 5033 Building(单调栈维护凸包)


    盗张图:来自http://blog.csdn.net/xuechelingxiao/article/details/39494433

    题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度,给出一个X坐标,高度为0,问X位置能看到的视角是多少度。如图:

    图一:bubuko.com,布布扣  

    图二:bubuko.com,布布扣

    图一为样例一,图二为样例三,红色部分为高楼,蓝色虚线为视角的最大范围。

    思路:维护一个上凸的凸壳,递减的。也就是这样的。

    分别找一下左边的和右边的就可以求出来答案

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 100005;
    const double PI = acos(-1);
    struct Node {
        int x, h;
        bool operator < (const Node &a) const {
            return x < a.x;
        }
    }node[maxn<<2], stack[maxn<<2];
    int T, n, q;
    double ans[maxn];
    
    int check(Node &a, Node &b, Node c) {  
        if (c.h <= 0)  
            c.h = 0;  
        return (long long)(b.x - a.x) * (c.h - a.h) >= (long long)(c.x - a.x) * (b.h - a.h);//前面一定要加上long long ,或者用double也行,不然他的乘积有可能爆int 
    } 
    double getAngle(const Node &p1, const Node &p2)
    {
        return atan((double)(p2.x - p1.x) / (double)p1.h);
    }
    void solve()
    {
        int head = 0;
        for (int i = 0; i < n + q; i++)
        {
            if (node[i].h <= 0)
            {
                while (head >= 2 && check(stack[head - 2], stack[head - 1], node[i]))
                    head--;
                ans[-node[i].h] += getAngle(stack[head - 1], node[i]);
            }
            else
            {
                while (head && stack[head - 1].h <= node[i].h)
                    head--;
                while (head >=2 && check(stack[head - 2], stack[head - 1], node[i]))
                    head--;
                stack[head++] = node[i];
            }
        }
    }
    int main()
    {
        int kase = 0;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d", &n);
            for (int i = 0; i < n; i++)
                scanf("%d %d", &node[i].x, &node[i].h);
            scanf("%d", &q);
            for (int i = 0; i < q; i++)
            {
                scanf("%d", &node[i + n].x);
                node[i + n].h = -i;
            }
            memset(ans, 0, sizeof(ans));
            sort(node, node + n + q);
            solve();
            reverse(node, node + n + q);
            for (int i = 0; i < n + q; i++)
                node[i].x = 10000000 - node[i].x;
            solve();
            printf("Case #%d:
    ", ++kase);
            for (int i = 0; i < q; i++)
                printf("%.10f
    ", ans[i] * 180.0 / PI);
        }
        return 0;
    }
  • 相关阅读:
    flask强大的三方组件flask-Migrate
    FTP和HTTP
    MD5-JS加密
    使用websocket实现单聊和多聊
    Flask上下文管理
    python中的with用法
    如何判断一个对象是可调用对象
    缓存
    websocket与http
    csrf
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4835689.html
Copyright © 2020-2023  润新知