[poj 3335]Rotating Scoreboard[半平面交模板题]

题意:

判断一个多边形内是否存在核。

思路:

半平面交的模板题。

用半平面交来求多边形的核可以用在线算法还实现,这个算法把问题分解成凸多边形与半平面相交(这个半平面的分界线就是题目中的多边形的每一条边)。求凸多边形与半平面的交集的做法是,先定义一个空的多边形,枚举多边形的点,若点在半平面内就加到这里定义的多边形的点集里,若与多边形的边相交就计算交点,再把交点也放到点集里。


找到一个看起来很顺眼的模板:

#include <cstdio>
#define vector point
const double INF =  1e18;
struct point
{
    double x,y;
    point(double xx = 0,double yy = 0)
    {
        x = xx;
        y = yy;
    }
    point operator - (const point& s)
    {
        return point(x - s.x, y - s.y);
    }
    point operator + (const point& s)
    {
        return point(x + s.x,y + s.y);
    }
};
struct polygon
{
    point p[100];
    int size;
};
struct line
{
    point first,second;
    line(point p1 = point(),point p2 = point())
    {
        first = p1;
        second = p2;
    }
};

double cross_product(vector v1,vector v2)
{
    return v1.x * v2.y - v1.y * v2.x;
}
//点积
double dot_product(vector v1,vector v2)
{
    return v1.x * v2.x + v1.y * v2.y;
}

//求两直线交点
point line_intersection(line ln1,line ln2)
{
    double a1,b1,c1,a2,b2,c2;
    a1 = ln1.first.y - ln1.second.y;
    b1 = ln1.second.x - ln1.first.x;
    c1 = cross_product(ln1.first, ln1.second);
    a2 = ln2.first.y - ln2.second.y;
    b2 = ln2.second.x - ln2.first.x;
    c2 = cross_product(ln2.first, ln2.second);
    double d = a1 * b2 - a2 * b1;
    return point((b1 * c2 - b2 * c1) / d,(c1 * a2 - c2 * a1) / d);
}

//一个多边形与一个半平面的交集
polygon half_plane_intersection(polygon& poly,line& ln)
{
    int m = 0;
    polygon hull;
    point p1 = ln.first,p2 = ln.second;
    //穷举多边形的所有点,判断是否在半平面上
    //如果凸多边形hull与直线ln有交点就求交点
    for(int i = 0;i < poly.size;i++)
    {
        double c = cross_product(p2 - p1,poly.p[i] - p1);
        double d = cross_product(p2 - p1,poly.p[(i + 1) % poly.size] - p1);
        //点poly.p[i]在半平面上
        if(c >= 0)
            hull.p[m++] = poly.p[i];
        //有交点
        if(c * d < 0)
        {
            hull.p[m++] = line_intersection(line(poly.p[(i + 1) % poly.size],poly.p[i]),ln);
            //printf("intersect = ( %g, %g)\n",hull.p[m - 1].x,hull.p[m - 1].y);
        }
    }
    //printf("\n\n");
    hull.size = m;
    return hull;
}

bool polygon_kernel(polygon& poly,polygon& knl)
{
    //initialized as infinite
    knl.p[0] = point(-INF,-INF);
    knl.p[1] = point(INF,-INF);
    knl.p[2] = point(INF,INF);
    knl.p[3] = point(-INF,INF);
    knl.size = 4;
    line ln;
   // point pre = poly.p[0];
    for(int i = 1;i <= poly.size;i++)
    {
        ln.first = poly.p[i % poly.size];      //the input is clockwise
        ln.second = poly.p[i - 1];
        knl = half_plane_intersection(knl,ln);
        if(knl.size == 0)
            return false;
    }
    return true;
}

int main()
{
    int t,n;
    polygon poly,knl;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 0;i < n;i++)
            scanf("%lf%lf",&poly.p[i].x,&poly.p[i].y);
        poly.size = n;
        if(polygon_kernel(poly,knl))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}


你可能感兴趣的:([poj 3335]Rotating Scoreboard[半平面交模板题])