您的位置:首页 > 产品设计 > UI/UE

Hdu 5033 Building(2014 ACM/ICPC Asia Regional Beijing Online1002) [几何]

2014-10-15 08:06 501 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033

问题的意思很是简单。一些高楼N<= 10^5,问一些人Q<=10^5处在高楼之间最大的视野角度。10^5次询问。比较痛苦。

一开始,因为就一简单的计算几何,直接就暴力写了。果断TLE。后来一看数据范围,我就给自己跪了。。这么大是数据量,果断会超时的。。看来还需要继续学习啊!!

后来看了题解,只能说计算几何仍然需要努力学习啊。。!!

很巧妙的一个思路。

离线来搞,把需要询问的点加到高楼里,当做高楼来搞,维护一个半凸包。。看下图:



这样就很好的来求解了。。思路巧妙,代码简单。。

Code:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;

const int N = 1e5 * 2 + 5;
const double eps = 1e-8;
const double pi = acos(-1.0);

struct POINT
{
    double x, y;
    int id;
    POINT() {
        id = -1;
    }
    POINT(double xx, double hh){
        x = xx;
        y = hh;
        id = -1;
    }
}p
, st
;
int n, q;
double ans
;

bool cmp(POINT a, POINT b)
{
    if(a.x < b.x) return true;
    return false;
}

double cross(POINT o, POINT a, POINT b)
{
    return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}

void solve()
{
    int top = 0;
    st[top ++] = p[1];
    st[top ++] = p[2];
    if(p[2].y == 0){// special judge if second point is the person's position..
        ans[p[2].id] += atan(p[1].y / (p[2].x - p[1].x));
    }
    for(int i = 3; i < n; i ++){
        while(top >= 2 && cross(st[top - 1], p[i], st[top - 2]) > eps) top --;
        st[top ++] = p[i];
        if(p[i].y == 0.0){
            ans[p[i].id] += atan(st[top - 2].y / (st[top - 1].x - st[top - 2].x));
        }
    }
}

void reverse()
{
    for(int i = 1; i <= n; i ++){
        p[i].x = 1e8 * 1.0 - p[i].x;
    }
}

void Init()
{
    for(int i = 1;  i <= q; i ++){
        ans[i] = 0.0;
    }
}
int main()
{
//    freopen("1.txt", "r", stdin);
    int T, k = 0;
    scanf("%d", &T);
    while(T --){
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++){
            scanf("%lf %lf", &p[i].x, &p[i].y);
        }
        scanf("%d", &q);
        Init();
        double x;
        for(int i = 1; i <= q; i ++){
            scanf("%lf", &x);
            p[i + n].x = x; p[i + n].y = 0.0;
            p[i + n].id = i;
        }

        n = n + q;
        sort(p + 1, p + 1 + n, cmp);
        solve();
        reverse();
        sort(p + 1, p + 1 + n, cmp);
        solve();

        printf("Case #%d:\n", ++ k);
        for(int i = 1; i <= q; i ++){
            printf("%.10lf\n", 180.0 - ans[i] / pi * 180.0);
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: