POJ 3335 Rotating Scoreboard 半平面交

题意:链接

方法:半平面交判定多边形内核存在性。

解析:

半平面交裸题。

练模板题。

首先按照逆时针搞出所有的边。

然后极角排序。

之后搞一个双端队列,维护原来的交点在新加的直线的左边。

最后扫一下队列即可。

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 110
#define eps 1e-8
using namespace std;
int t,n,halfplanes;
struct Point
{
    double x,y;
    Point(){}
    Point(double a,double b){x=a,y=b;}
    Point operator + (const Point &a)
    {return Point(x+a.x,y+a.y);}
    Point operator - (const Point &a)
    {return Point(x-a.x,y-a.y);}
    Point operator * (double rate)
    {return Point(x*rate,y*rate);}
    double operator * (const Point &a)
    {return x*a.x+y*a.y;}
    double operator ^ (const Point &a)
    {return x*a.y-y*a.x;} 
}p[N],pt[N];
struct HalfPlane
{
    Point p,v;
    double angle;
    HalfPlane(){}
    HalfPlane(Point _s,Point _t):p(_s),v(_t)
    {
        angle=atan2(v.y,v.x);
    }
    friend bool operator < (HalfPlane a,HalfPlane b)
    {
        return a.angle<b.angle;
    }
}hp[N],q[N];
Point Get_Intersection(HalfPlane &l1,HalfPlane &l2)
{
    Point u=l1.p-l2.p;
    double tmp=(l2.v^u)/(l1.v^l2.v);
    return l1.p+l1.v*tmp;
}
bool onleft(HalfPlane &L,Point p)
{
    return (L.v^(p-L.p))>=0;
} 
int HalfPlaneIntersect()
{
    int l=1,r=1;
    q[1]=hp[1];
    for(int i=2;i<=halfplanes;i++)
    {
        while(l<r&&!onleft(hp[i],p[r-1]))r--;
        while(l<r&&!onleft(hp[i],p[l]))l++;
        if(fabs(hp[i].v^q[r].v)<eps)
            q[r]=onleft(q[r],hp[i].p)?hp[i]:q[r];
        else q[++r]=hp[i];
        if(l<r)p[r-1]=Get_Intersection(q[r],q[r-1]);
    }
    while(l<r&&!onleft(q[l],p[r-1]))r--;
    return r-l>1;
}
void MakeLine(Point &a,Point &b)
{
    hp[++halfplanes]=HalfPlane(a,b-a);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        halfplanes=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&pt[i].x,&pt[i].y);
        for(int i=1;i<n;i++)
            MakeLine(pt[i+1],pt[i]);
        MakeLine(pt[1],pt[n]);
        sort(hp+1,hp+halfplanes+1);
        int ans=HalfPlaneIntersect();
        if(ans)puts("YES");
        else puts("NO");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值