半平面交。
判断多边形核是否存在,用半平面交。
半平面交资料传送门:算法合集之《半平面交的新算法及其实用价值》
提交的时候语言选错,蜜汁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");
}
}