Rotating Scoreboard - POJ 3335(半面相交求多边形内核)

时间:2023-03-09 06:41:44
Rotating Scoreboard - POJ 3335(半面相交求多边形内核)

题目大意:RT

分析:所谓内核可以理解为在多边形内存在点可以在这个点上看到多边形内部所有的部分,当然怎么求出来就是问题的关键了。我们知道多边形的每条边都是边界值,边的左边和右边肯定是一部分属于多边形一部分属于多边形外,如果这个多边形是顺时针的话那么右边就属于里面,左边就属于外边,如果这条变的外边那么一定是看不到这条边的了,所以可以排出。具体做法如下:

Rotating Scoreboard - POJ 3335(半面相交求多边形内核)

如上图所示:这个多边形按照顺时针来的,有5个顶点,分别是12345,首先我们先把边12拿出,发现,123都属于边12的右边,45不属于,所以可以吧45扔掉,但是我们发现12和34相交与点A,所以当发现有点在左边的时候需要判断一下它所连接的线是否和这条线有交点,如果有把交点保存下来,可以使用叉积判断左右边。

代码如下:


#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std; const int MAXN = ;
const int oo = 1e9+;
const double EPS = 1e-; int Sign(double t)
{
if(t > EPS)
return ;
if(fabs(t) < EPS)
return ;
return -;
} struct Point
{
double x, y;
Point(double x=, double y=):x(x),y(y){}
Point operator - (const Point &t)const{
return Point(x-t.x, y-t.y);
}
double operator ^(const Point &t)const{
return x*t.y - y*t.x;
} }p[MAXN], in[MAXN];
struct Segment
{///ax + by = c
Point S, E;
double a, b, c;
Segment(Point S=, Point E=):S(S), E(E){
a = S.y - E.y;
b = E.x - S.x;
c = E.x*S.y - S.x*E.y;
}
Point crossNode(const Segment &t)const{
Point res; res.x = (c*t.b-t.c*b) / (a*t.b-t.a*b);
res.y = (c*t.a-t.c*a) / (b*t.a-t.b*a); return res;
}
int Mul(const Point &t)
{///用叉积判断方向
return Sign((E-S)^(t-S));
}
};
int CutPoly(Segment L, int N)
{
Point tmp[MAXN];
int cnt = ; for(int i=; i<=N; i++)
{
if(L.Mul(in[i]) <= )
tmp[++cnt] = in[i];
else
{
if(L.Mul(in[i-]) < )///求出交点
tmp[++cnt] = L.crossNode(Segment(in[i-],in[i]));
if(L.Mul(in[i+]) < )
tmp[++cnt] = L.crossNode(Segment(in[i],in[i+]));
}
} for(int i=; i<=cnt; i++)
in[i] = tmp[i];
in[] = in[cnt], in[cnt+] = in[]; return cnt;
} int main()
{
int N; while(scanf("%d", &N) != EOF && N)
{
int M; for(int i=; i<=N; i++)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
in[i] = p[i];
}
in[] = p[] = p[N];
in[N+] = p[N+] = p[];
M = N; for(int i=; i<=N; i++)
M = CutPoly(Segment(p[i],p[i+]), M); if(M > )
printf("YES\n");
else
printf("NO\n");
} return ;
}