题目:
题意:
给出一个多边形,判断多边形是否有核
题解:
所谓多边形的核,简单来说就是有个人站在这个点,那么这个多边形内的每一个点这个人都能看见(光沿直线传播)
也就是说对于多边形的每一条边的一个半平面求交,可以交出来一个凸壳,这个点集中的点都满足要求
附图
这就是一道半平面交裸题了
诶等等我好像还不会半平面交
给出若干个半平面,求它们的交
也就是类似数学必修五的线性规划问题
半平面交的答案是一个凸壳
首先初始化的时候给它加上一个很大的框
然后每一次加入一条直线,将直线左边的点保留,并且计算出来这条直线和当前凸壳的交点加入,时间复杂度
O(n2)
void init()
{
cnt=0;
poly[++cnt]=Point(inf,inf);
poly[++cnt]=Point(inf,-inf);
poly[++cnt]=Point(-inf,-inf);
poly[++cnt]=Point(-inf,inf);
}
void halfp(Point A,Point B)
{
ncnt=0;
Point C,D;
for (int i=1;i<=cnt;++i)
{
C=poly[i%cnt+1];
D=poly[(i+1)%cnt+1];
if (dcmp(Cross(B-A,C-A))<=0)
npoly[++ncnt]=C;
if (insLS(A,B,C,D))
npoly[++ncnt]=GLI(A,B-A,C,D-C);
}
cnt=ncnt;
for (int i=1;i<=cnt;++i)
poly[i]=npoly[i];
}
think less,time more
特别要注意判断insLS是直线与线段是否相交!
这里只是判断一个交点并不是重合,如果重合的话一定是两条平行直线,中间省去一个点没加也可以
代码:
#include <cstdio>
using namespace std;
const double INF=1e9;
const double eps=1e-9;
int dcmp(double x)
{
if (x<=eps && x>=-eps) return 0;
return (x>0)?1:-1;
}
struct po
{
double x,y;
po (double X=0,double Y=0){x=X;y=Y;}
}p[55],np[55],d[55];
int cnt,ncnt;
po operator -(po x,po y){return po(x.x-y.x,x.y-y.y);}
po operator +(po x,po y){return po(x.x+y.x,x.y+y.y);}
po operator *(po x,double y){return po(x.x*y,x.y*y);}
double cj(po x,po y){return x.x*y.y-x.y*y.x;}
void init()
{
cnt=0;
p[++cnt]=po(-INF,-INF);
p[++cnt]=po(INF,-INF);
p[++cnt]=po(INF,INF);
p[++cnt]=po(-INF,INF);
}
bool have(po a,po b,po c,po d){return dcmp(cj(b-a,c-a))!=dcmp(cj(b-a,d-a));}
po jd(po a,po b,po c,po d){return a+b*(cj(c-a,d)/cj(b,d));}
void hp(po A,po B)
{
ncnt=0;
po C,D;
for (int i=1;i<=cnt;i++)
{
C=p[i%cnt+1];
D=p[(i+1)%cnt+1];
if (dcmp(cj(B-A,C-A))>=0) np[++ncnt]=C;
if (have(A,B,C,D)) np[++ncnt]=jd(A,B-A,C,D-C);
}
cnt=ncnt;
for (int i=1;i<=cnt;i++) p[i]=np[i];
}
int main()
{
int n;
while (scanf("%d",&n)&&n)
{
double x,y;
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&x,&y);
d[i]=po(x,y);
}
init();
for (int i=1;i<=n;i++)
hp(d[i%n+1],d[(i+1)%n+1]);
if (cnt) printf("1\n");else printf("0\n");
}
}