POJ 3335(半平面交—判断多边形的核是否存在)

Rotating Scoreboard
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 7444 Accepted: 2977
Description

This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spectators are seated along the edges of the polygon. We want to place a rotating scoreboard somewhere in the hall such that a spectator sitting anywhere on the boundary of the hall can view the scoreboard (i.e., his line of sight is not blocked by a wall). Note that if the line of sight of a spectator is tangent to the polygon boundary (either in a vertex or in an edge), he can still view the scoreboard. You may view spectator’s seats as points along the boundary of the simple polygon, and consider the scoreboard as a point as well. Your program is given the corners of the hall (the vertices of the polygon), and must check if there is a location for the scoreboard (a point inside the polygon) such that the scoreboard can be viewed from any point on the edges of the polygon.

Input

The first number in the input line, T is the number of test cases. Each test case is specified on a single line of input in the form n x1 y1 x2 y2 … xn yn where n (3 ≤ n ≤ 100) is the number of vertices in the polygon, and the pair of integers xi yi sequence specify the vertices of the polygon sorted in order.

Output

The output contains T lines, each corresponding to an input test case in that order. The output line contains either YES or NO depending on whether the scoreboard can be placed inside the hall conforming to the problem conditions.

Sample Input

2
4 0 0 0 1 1 1 1 0
8 0 0 0 2 1 2 1 1 2 1 2 2 3 2 3 0
Sample Output

YES
NO
Source

Tehran 2006 Preliminary

开始听到半平面交觉得好复杂啊,这啥东西,核是啥,一直不敢尝试(怠惰),学了之后就觉得,啊这个啊,不是我们高中学的嘛!
半平面交和高中学的线性规划差不多;
什么是半平面交?

·半平面:平面上的直线及其一侧的部分。 ·半平面可由不等式ax+by+c>=0确定。
·在一个有界区域里半平面或半平面的交是一个凸多边形区域。 ·n个半平面的交是一个至多n条边的凸多边形。

再看看什么是多边形的核:

它是平面简单多边形的核是该多边形内部的一个点集,该点集中任意一点与多边形边界上一点的连线都处于这个多边形内部。

如何求解?
这篇博文是带图的,可以很好理解 戳这里
论实现方法有两种,一种是nlogn ,一种是n^2目前只学了后者,前者日后再学
本题就是判断多边形的核是不是存在,判断方法就是求出多边形的核,看它的顶点数目是不是0即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn 110
#define maxe 100010
typedef long long ll;
using namespace std;
const double eps=1e-5;
const int inf=0x3f3f3f3f3f;
typedef double T1;
struct Point
{
    T1 x,y;
    Point(){};
    Point(T1 a,T1 b)
    {
        x=a,y=b;
    }
    void input()
    {
        scanf("%lf%lf",&x,&y);
    }
    Point operator +(Point a)
    {
        Point b(x+a.x,y+a.y);
        return b;
    }
    Point operator -(Point a)
    {
        Point b(x-a.x,y-a.y);
        return b;
    }
    T1 operator *(Point a)
    {
        return x*a.x+y*a.y;
    }
    T1 operator ^(Point a)
    {
        return x*a.y-y*a.x;
    }
    bool operator <(Point a)
    {
        return x//求解 由 P1,P2确定的ax+by+c=0的参数
void Get_equation(Point p1,Point p2,double &a,double &b,double &c)
{
    a=p1.y-p2.y;
    b=p2.x-p1.x;
    c=p1.x*p2.y-p1.y*p2.x;
}
//线段p1,p2和直线ax+by+c的交点
Point intersection(Point p1,Point p2,double a,double b,double c)
{
    double u=fabs(a*p1.x+b*p1.y+c);
    double v=fabs(a*p2.x+b*p2.y+c);
    Point t;
    t.x=(p1.x*v+p2.x*u)/(u+v);
    t.y=(p1.y*v+p2.y*u)/(u+v);
    return t;
}
Point pap[maxn];
Point tmp[maxn];
//求解多边形的核
void Cut(Point point[],int &cnt,double a,double b,double c)
{
    int t=0;
    //看p[i]是不是在所确定直线的顺时针方向,如果是的话就加入答案,不是的话就说明直线一定和以这个点为端点的线段有交点,加入这个交点即可。
    for(int i=1;i<=cnt;i++)
    {
        if(a*point[i].x+b*point[i].y+c<=eps)pap[++t]=point[i];
        else
        {
            if(a*point[i-1].x+b*point[i-1].y+c1],point[i],a,b,c);
            if(a*point[i+1].x+b*point[i+1].y+c1],point[i],a,b,c);
        }

    }
    for(int i=1;i<=t;i++)
    {
        point[i]=pap[i];
    }
    point[0]=pap[t];
    point[t+1]=pap[1];
    cnt=t;
}
int main()
{
    int t;
    int n;
    //freopen("in.txt","r",stdin);
    scanf("%d",&t);

    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            p[i].input();
        }
        double a,b,c;
        p[n+1]=p[1];
        p[0]=p[n];
        int cnt=n;
        int flag=1;
        for(int i=0;i<=n+1;i++)
        {
            tmp[i]=p[i];
        }
        for(int i=1;i<=n;i++)
        {
            Get_equation(p[i],p[i+1],a,b,c);
            Cut(tmp,cnt,a,b,c);
        }
        if(cnt)puts("YES");
        else puts("NO");

    }
    return 0;
}

你可能感兴趣的:(计算几何)