[POJ]2451: Uyuw's Concert

本文介绍了一个关于计算有限制条件下舞台最大面积的问题解决方法。利用半平面交模板,通过具体的C++实现,详细展示了如何处理有向线段来确定舞台的最大可能区域。

题目大意:一个10000*10000的舞台,N条有向线,线左边才能布置舞台,求最后舞台面积。(N<=20000)

思路:半平面交模板。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define MN 20000
#define eps 1e-7
struct point{double x,y;point(double x=0,double y=0):x(x),y(y){}}p[MN+5];
point operator+(point a,point b){return point(a.x+b.x,a.y+b.y);}
point operator-(point a,point b){return point(a.x-b.x,a.y-b.y);}
point operator*(point a,double x){return point(a.x*x,a.y*x);}
double operator*(point a,point b){return a.x*b.y-a.y*b.x;}
struct line{point p,v;line(double a=0,double b=0,double c=0,double d=0):p(a,b),v(c,d){}}l[MN+5];
bool cmp(line a,line b){return atan2(a.v.y,a.v.x)<atan2(b.v.y,b.v.x);}
bool left(line l,point p){return l.v*(p-l.p)<0;}
point xp(line a,line b){return a.p+a.v*(b.v*(a.p-b.p)/(a.v*b.v));}
int q[MN+5],ql,qr;
int main()
{
    int n,i;double ans=0;
    scanf("%d",&n);
    for(i=0;i<n;++i)
        scanf("%lf%lf%lf%lf",&l[i].p.x,&l[i].p.y,&l[i].v.x,&l[i].v.y),
        l[i].v.x-=l[i].p.x,l[i].v.y-=l[i].p.y;
    l[n++]=line(0,0,10000,0);
    l[n++]=line(10000,0,0,10000);
    l[n++]=line(10000,10000,-10000,0);
    l[n++]=line(0,10000,0,-10000);
    sort(l,l+n,cmp);
    for(i=1;i<n;++i)
    {
        while(ql<qr&&left(l[i],p[qr-1]))--qr;
        while(ql<qr&&left(l[i],p[ql]))++ql;
        if(q[++qr]=i,fabs(l[q[qr-1]].v*l[i].v)<eps)
            if(left(l[i],l[q[--qr]].p))q[qr]=i;
        if(ql<qr)p[qr-1]=xp(l[q[qr]],l[q[qr-1]]);
    }
    while(ql<qr&&left(l[q[ql]],p[qr-1]))--qr;
    p[qr]=xp(l[q[qr]],l[q[ql]]);
    for(i=ql;++i<qr;)ans+=(p[i]-p[ql])*(p[i+1]-p[ql]);
    printf("%.1f",ans/2);
}

 

转载于:https://www.cnblogs.com/ditoly/p/POJ2451.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值