首页 > 其他 > 详细

[CQOI2006]凸多边形

时间:2020-01-07 09:47:09      阅读:55      评论:0      收藏:0      [点我收藏+]

题目

wdnmd可算调出来了,以后我也是会半平面交的人了

由于给定的是一些凸包,我们直接按照逆时针把所有直线搞下来,我们默认保留直线左边的半平面;之后我们就可以按照极角序把直线排序,对于两条极角相等的直线,显然是更靠近左边的优,于是我们只保留最靠左的直线

与凸包不同的是,我们使用一个双端队列维护半平面交,对于一条要插入的直线\(l\),我们发现队尾两条直线的交点\(p\)\(l\)的右侧,那么就说明队尾的直线没啥用了,就弹出去;同理,如果队首两条直线的交点在\(l\)右侧,也将队首直线弹出

可以康康这个老哥博客里的图

最后还有可能出现队尾两条直线的交点在队首直线的右侧的情况,对于这种情况我们弹掉队尾就好了

代码

#include<bits/stdc++.h>
#define re register
const int maxn=505;
struct Point{double x,y;}p[maxn],a[maxn],S;
const double eps=1e-8;
int n,cnt,tot,h,t,tmp;
struct Line{Point s,t;double det;}L[maxn],q[maxn];
inline Point operator+(Point A,Point B) {return (Point){A.x+B.x,A.y+B.y};}
inline Point operator-(Point A,Point B) {return (Point){A.x-B.x,A.y-B.y};}
inline Point operator^(double g,Point C) {return (Point){C.x*g,C.y*g};}
inline double operator*(Point A,Point B) {return A.x*B.y-B.x*A.y;}
inline int dcmp(double A,double B) {return A+eps>B&&A-eps<B;}
inline int OnRight(const Point &a,const Line &c) {
    return (c.t-a)*(c.s-a)>0;
}
inline int cmp(const Line &A,const Line &B) {
    return dcmp(A.det,B.det)?OnRight(A.s,B):(A.det<B.det);
}
inline Point sec(const Line &A,const Line &B) {
    Point v1=A.t-A.s,v2=B.t-B.s,v3=A.s-B.s;
    double t=(v3*v2)/(v2*v1);
    return A.s+(t^v1);
}
int main() {
    scanf("%d",&n);S.x=1e18,S.y=1e18;
    for(re int m,i=1;i<=n;i++) {
        scanf("%d",&m);
        for(re int j=1;j<=m;j++) scanf("%lf%lf",&a[j].x,&a[j].y);
        for(re int j=1;j<m;++j) L[++cnt].s=a[j],L[cnt].t=a[j+1];
        L[++cnt].s=a[m],L[cnt].t=a[1];
    }
    for(re int i=1;i<=cnt;i++) 
        L[i].det=atan2((L[i].t-L[i].s).y,(L[i].t-L[i].s).x);
    std::sort(L+1,L+cnt+1,cmp);h=1,t=0;tot=0;
    for(re int i=1;i<=cnt;i++) {
        if(!dcmp(L[i].det,L[i-1].det)) ++tot;
        L[tot]=L[i];
    }
    q[++t]=L[1],q[++t]=L[2];
    for(re int i=3;i<=tot;i++) {
        while(h<t&&OnRight(sec(q[t],q[t-1]),L[i])) --t;
        while(h<t&&OnRight(sec(q[h],q[h+1]),L[i])) ++h;
        q[++t]=L[i];
    }
    while(h<t&&OnRight(sec(q[t],q[t-1]),q[h])) --t;
    while(h<t&&OnRight(sec(q[h],q[h+1]),q[t])) ++h;
    for(re int i=h;i<t;i++) p[++tmp]=sec(q[i],q[i+1]);p[++tmp]=sec(q[t],q[h]);
    double ans=p[tmp]*p[1];
    for(re int i=1;i<tmp;i++) ans+=p[i]*p[i+1];
    printf("%.3lf\n",ans*0.5);return 0;
}

[CQOI2006]凸多边形

原文:https://www.cnblogs.com/asuldb/p/12159471.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!