现在的位置: 首页 > 综合 > 正文

ZOJ 1248 Video Surveillance(半平面交)

2019年02月11日 ⁄ 综合 ⁄ 共 2568字 ⁄ 字号 评论关闭

判断一个多边形是否有核。


大体思想是,用多边形的边构成的直线,一点一点去削去原多边形。


蓝色区域则为多边形的核。

判断大于0还是小于0有一个小技巧:直线走向的左手边是小于0的,右手边是大于0的。

向量AB等于点B减去点A,走向为A指向B。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
#define MAXN 2010
#define eps 1e-10
#define max(x, y) (x > y ? x : y)
#define min(x, y) (x < y ? x : y)
#define sig(x) ((x > eps) - (x < -eps))
#define cross(o, a, b) ((p[a] - p[o]) ^ (p[b] - p[o]))

const double pi = acos(-1.0);

typedef struct Point
{
        double x, y;
        Point() {}
        Point(double _x, double _y):
                x(_x), y(_y) {}
        bool operator <(const Point &argu) const
        {
            return sig(x - argu.x) == 0 ? y < argu.y : x < argu.x;
        }
        double dis(const Point &argu) const
        {
            return sqrt((x - argu.x) * (x - argu.x) + (y - argu.y) * (y - argu.y));
        }
        double dis2(const Point &argu) const
        {
            return (x - argu.x) * (x - argu.x) + (y - argu.y) * (y - argu.y);
        }
        double operator ^(const Point &argu) const
        {
            return x * argu.y - y * argu.x;
        }
        double operator *(const Point &argu) const
        {
            return x * argu.x + y * argu.y;
        }
        Point operator -(const Point &argu) const
        {
            return Point(x - argu.x, y - argu.y);
        }
        double len2() const
        {
            return x * x + y * y;
        }
        double len() const
        {
            return sqrt(x * x + y * y);
        }
        void in()
        {
            scanf("%lf%lf", &x, &y);
        }
        void out()
        {
            printf("%.3lf %.3lf\n", x, y);
        }
}Vector;

inline double Cross(const Point &o, const Point &a, const Point &b)
{
    return (a - o) ^ (b - o);
}

Point Get_Intersection(const Point &u1, const Point &u2, const Point &v1, const Point &v2)
{
    Point ret = u1;
    double t = ((u1.x - v1.x) * (v1.y - v2.y) - (u1.y-v1.y) * (v1.x - v2.x))
            / ((u1.x - u2.x) * (v1.y - v2.y) - (u1.y - u2.y) * (v1.x - v2.x));
    ret.x += (u2.x - u1.x) * t;
    ret.y += (u2.y - u1.y) * t;
    return ret;
}

Point Get_Intersection(const Point &x, const Point &y, double a, double b, double c)
{
    double u = fabs(a * x.x + b * x.y + c);
    double v = fabs(a * y.x + b * y.y + c);
    return Point((x.x * v + y.x * u) / (u + v), (x.y * v + y.y * u) / (u + v));
}

void Get_Line(const Point &x, const Point &y, double &a, double &b, double &c)
{
    a = y.y - x.y;
    b = x.x - y.x;
    c = y.x * x.y - x.x * y.y;
}

Point q[MAXN];
int Cut(Point p[], double a, double b, double c, int n)
{
    int cc = 0;
    for(int i = 1; i <= n; i++)
    {
        double k = a * p[i].x + b * p[i].y + c;
        if(sig(k) >= 0) q[++cc] = p[i];
        else
        {
            double k1 = a * p[i - 1].x + b * p[i - 1].y + c;
            double k2 = a * p[i + 1].x + b * p[i + 1].y + c;
            if(k1 > 0) q[++cc] = Get_Intersection(p[i], p[i - 1], a, b, c);
            if(k2 > 0) q[++cc] = Get_Intersection(p[i], p[i + 1], a, b, c);
        }
    }
    for(int i = 1; i <= cc; i++) p[i] = q[i];
    p[cc + 1] = q[1], p[0] = p[cc];
    return cc;
}

int solve(Point pp[], Point ke[], int n)
{
    int cc = n;
    for(int i = 1; i <= n; i++)
    {
        double a, b, c;
        Get_Line(pp[i], pp[i + 1], a, b, c);
        cc = Cut(ke, a, b, c, cc);
    }
    if(cc >  0) return 0;
    if(cc <= 0) return 1;
}

char ans[2][30] = {
    "Surveillance is possible.",
    "Surveillance is impossible." };
Point pp[MAXN], ke[MAXN];
int n;

int main()
{
//    freopen("J.in", "r", stdin);

    int cas = 1;
    while(scanf("%d", &n) && n)
    {
        for(int i = 1; i <= n; i++) pp[i].in(), ke[i] = pp[i];
        ke[n + 1] = pp[n + 1] = pp[1];
        ke[0] = pp[0] = pp[n];
        printf("Floor #%d\n%s\n\n", cas++, ans[solve(pp, ke, n)]);
    }
    return 0;
}

抱歉!评论已关闭.