HDU 5033 Building(模拟凸包建立过程)

来源:互联网 发布:软件开发全面质量管理 编辑:程序博客网 时间:2024/04/29 16:17

题目链接:

传送门

题意:

在坐标轴上有n个点,每个点的有一个建筑物,高度为h,求一个人站在坐标为(x,0)的位置所能看到的天空的角度。

分析:

我们将询问的点(x,0)也插入到给定的点中,然后建立一个模拟建立凸包的过程,凸包上的一个点一定要与它相邻点的斜率一定要大于与它相邻的点x1x1相邻的点x2 的斜率。因此我们正着求一次凸包得到每个点与左边形成的角度,然后再倒着做一次凸包求出与右边形成的角度即可。

Code

#include <bits/stdc++.h>using namespace std;const int maxn = 2e5+10;const double eps = 1e-10;const double pi = acos(-1.0);int dcmp(double x) {    if(fabs(x)<eps) return 0;    else return x < 0 ? -1 : 1;}struct Point {    double x, y;    int id;    double thea1,thea2;    bool operator < (const Point& a) const {        return x < a.x;    }    bool operator == (const Point B)const {        return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;    }} p[maxn],st[maxn];double calc(Point a,Point b){    return (b.y-a.y)/fabs(b.x-a.x);}bool cmp(const Point &A,const Point &B){    return A.id<B.id;}int main(){    int t,n,m,cas=1;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        for(int i=0;i<n;i++){            scanf("%lf%lf%",&p[i].x,&p[i].y);            p[i].id=i;        }        scanf("%d",&m);        for(int i=n;i<n+m;i++){            scanf("%lf",&p[i].x);            p[i].id=i;            p[i].y=0;        }        n+=m;        sort(p,p+n);        int top=0;        st[0]=p[0];        for(int i=1;i<n;i++){            if(p[i].id<n-m){                while(top&&calc(p[i],st[top])<calc(st[top],st[top-1])){                    top--;                }                st[++top]=p[i];            }            else{                int tmp = top;                while(tmp&&calc(p[i],st[tmp])<calc(p[i],st[tmp-1]))                    tmp--;                p[i].thea1=calc(p[i],st[tmp]);            }        }        top=0;        st[0]=p[n-1];        for(int i=n-2;i>=0;i--){            if(p[i].id<n-m){                while(top&&calc(p[i],st[top])<calc(st[top],st[top-1]))                    top--;                st[++top]=p[i];            }            else{                int tmp = top;                while(tmp&&calc(p[i],st[tmp])<calc(p[i],st[tmp-1]))                    tmp--;                p[i].thea2=calc(p[i],st[tmp]);            }        }        sort(p,p+n,cmp);        printf("Case #%d:\n",cas++);        for(int i=n-m;i<n;i++){            double thea = pi - atan(p[i].thea1)-atan(p[i].thea2);            printf("%.5lf%c",thea*180.0/pi,i==n-1 ? '\n' : ' ');        }    }    return 0;}
1 0