其实只是记一个板子(lll¬ω¬)
Description
内核是多边形内的一个点集,点集内任意一点与多边形边上任意一点的连线都在多边形内。你可以把多边形想成一个房间,在内核内任意一个点放上一个全方位360度无死角的摄像机,这个摄像机能够看到房间的任意角落。
现在给出一个n边形的所有顶点,求是否存在核
Solution
poj喜闻乐见地挂了,例题不知道过了没
可以发现这个核就是以边作为若干半平面的交。极角排序之后用双端队列可以做到nlogn维护半平面交,这里面涉及一些比较显然但是我不太会的计算几何姿势,板子是抄来的
这里直线用的是点+方向向量的表示,半平面规定为方向向量的左侧,直线求交有一些巧妙的做法
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <math.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=20005;
const double eps=1e-5;
struct Point {
double x,y;
Point() {}
Point(double X,double Y) {x=X,y=Y;}
Point operator +(const Point &B) const {
return (Point) {x+B.x,y+B.y};
}
Point operator -(const Point &B) const {
return (Point) {x-B.x,y-B.y};
}
Point operator *(const double &b) const {
return (Point) {x*b,y*b};
}
Point operator /(const double &b) const {
return (Point) {x*b,y*b};
}
bool operator <(const Point &B) const {
return (x<B.x)||(fabs(x-B.x)<=eps&&y<B.y);
}
} p[N],a[N];
typedef Point Vector;
struct Line {
Point p; Vector v;
double ang;
Line() {}
Line(Point P,Vector V) {
p=P,v=V; ang=atan2(v.y,v.x);
}
bool operator <(const Line &L) const {
return ang<L.ang;
}
} L[N],q[N];
double cros(const Point &A,const Point &B) {
return (B.y*A.x-B.x*A.y);
}
bool onLeft(const Point &A,const Line &B) {
return cros(B.v,A-B.p)>0;
}
Point inte(const Line &A,const Line &B) {
Vector v=A.p-B.p;
double tmp=cros(B.v,v)/cros(A.v,B.v);
return A.p+A.v*tmp;
}
bool solve(int n) {
std:: sort(L,L+n);
int head=0,tail=0;
q[head]=L[0];
rep(i,1,n-1) {
while (head<tail&&onLeft(p[tail-1],L[i])==0) tail--;
while (head<tail&&onLeft(p[head],L[i])==0) head++;
q[++tail]=L[i];
if (fabs(cros(q[tail].v,q[tail-1].v))<=eps) {
tail--;
if (onLeft(L[i].p,q[tail])) q[tail]=L[i];
}
if (head<tail) p[tail-1]=inte(q[tail-1],q[tail]);
}
while (head<tail&&onLeft(p[tail-1],q[head])==0) tail--;
return (tail-head>=2);
}
int main(void) {
freopen("data.in","r",stdin);
int n; scanf("%d",&n);
for (;n;scanf("%d",&n)) {
rep(i,0,n-1) scanf("%lf%lf",&a[i].x,&a[i].y);
L[0]=Line(a[n-1],a[0]-a[n-1]);
rep(i,1,n-1) L[i]=Line(a[i],a[i]-a[i-1]);
printf("%d\n", solve(n));
}
return 0;
}