POJ 3335 Rotating Scoreboard

本文介绍了一种基于半平面交的算法实现,用于判断多边形内是否存在核。通过定义结构体来表示点和直线,并使用atan2函数计算角度,最终通过比较不同线段之间的相对位置来确定多边形是否包含核。

半平面交。

判断多边形核是否存在,用半平面交。

半平面交资料传送门:算法合集之《半平面交的新算法及其实用价值》

提交的时候语言选错,蜜汁CE一次- -

#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 105
using namespace std;
struct point
{
    double x, y;
}p[N];
struct line
{
    point a, b;
    double angle;
}l[N];
int lcnt=0, rank[N], q[N];
int dblcmp(double k)
{
    if(fabs(k)<1e-8)return 0;
    return k>0?1:-1;
}
double multi(point a, point b, point c)
{
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
bool cmp(int a, int b)
{
    int d=dblcmp(l[a].angle-l[b].angle);
    if(!d){return dblcmp(multi(l[a].a,l[b].a,l[b].b))<0;}
    else return d>0;
}
void add_line(point a, point b)
{
    l[++lcnt]=(line){a,b,atan2(b.y-a.y,b.x-a.x)};
    rank[lcnt]=lcnt;
}
point intersect(line l1, line l2)  
{  
    point p;
    double dot1, dot2;  
    dot1 = multi(l2.a, l1.b, l1.a);  
    dot2 = multi(l1.b, l2.b, l1.a);  
    p.x = (l2.a.x * dot2 + l2.b.x * dot1) / (dot2 + dot1);  
    p.y = (l2.a.y * dot2 + l2.b.y * dot1) / (dot2 + dot1);  
    return p;
}  
bool judge(line l0, line l1, line l2)
{
    point p = intersect(l1,l2);
    return dblcmp(multi(p,l0.a,l0.b))>0;
}
bool HPI()
{
    sort(rank+1,rank+1+lcnt,cmp);
    int j=1;
    for(int i = 2; i <= lcnt; i++)
    {
        if(dblcmp(l[rank[i]].angle-l[rank[j]].angle))
            rank[++j]=rank[i];
    }
    lcnt=j; 
    int head=0, tail=2;
    q[0]=rank[1];
    q[1]=rank[2];
    for(int i = 3; i <= lcnt; i++)
    {
        while(tail-head>1 && judge(l[rank[i]],l[q[tail-1]],l[q[tail-2]]))tail--;
        while(tail-head>1 && judge(l[rank[i]],l[q[head]],l[q[head+1]]))head++;
        q[tail++]=rank[i];
    }
    while(tail-head>1 && judge(l[q[tail-1]],l[q[head]],l[q[head+1]]))head++;
    while(tail-head>1 && judge(l[q[head]],l[q[tail-1]],l[q[tail-2]]))tail--;
    return tail-head>2;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        lcnt=0;
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        for(int i = 1; i < n; i++)
            add_line(p[i],p[i+1]);
        add_line(p[n],p[1]);
        if(HPI())printf("YES\n");
        else printf("NO\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值