其他分享
首页 > 其他分享> > UVa 10256(凸包、线段交、点在多边形内)

UVa 10256(凸包、线段交、点在多边形内)

作者:互联网

要点

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

typedef double db;
const db PI = acos(-1);
const db eps = 1e-9;
const int maxn = 505;

int dcmp(db x) {
    if (fabs(x) < eps)  return 0;
    return x > 0 ? 1 : -1;
}

struct Point {
    db x, y;
    Point(){}
    Point(db a, db b):x(a), y(b){}
    bool operator < (const Point &rhs) const {
        if (dcmp(x - rhs.x) != 0)   return dcmp(x - rhs.x) < 0;
        return dcmp(y - rhs.y) < 0;
    }
};
typedef Point Vector;

Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }
bool operator == (const Vector& A, const Vector& B) { return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; }

db Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//点积

db Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }//叉积

bool isPointOnSegment(Point P, Point A, Point B) { return dcmp(Cross(A - P, B - P)) == 0 && dcmp(Dot(A - P, B - P)) <= 0; }//点在线段上(包含端点,把<=改为<即为不包含端点)

bool Segment_Proper_Intersection(Point a1, Point a2, Point b1, Point b2) {//线段a1a2与b1b2相交(包含端点)
    db c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
    db c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
    if (isPointOnSegment(a1, b1, b2) || isPointOnSegment(a2, b1, b2))//某点在另一条线段上
        return 1;
    if (isPointOnSegment(b1, a1, a2) || isPointOnSegment(b2, a1, a2))
        return 1;
    return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
}

int isPointInPolygon(Point p, Vector *poly, int poly_size) {
    if (poly_size == 1) return p == poly[0];//多边形退化成点的特判
    
    int wn = 0;
    int n = poly_size;
    for (int i = 0; i < n; i++) {
        if (isPointOnSegment(p, poly[i], poly[(i + 1) % n]))    return -1;//在边界上
        int k = dcmp(Cross(poly[(i + 1) % n] - poly[i], p - poly[i]));
        int d1 = dcmp(poly[i].y - p.y);
        int d2 = dcmp(poly[(i + 1) % n].y - p.y);
        if (k > 0 && d1 <= 0 && d2 > 0) wn++;
        if (k < 0 && d2 <= 0 && d1 > 0) wn--;
    }
    if (wn != 0)    return 1;//内部
    return 0;//外部
}

void ConvexHull(Point *p, int n, Point *v, int &cnt) {
    cnt = 0;
    sort(p, p + n);
    n = unique(p, p + n) - p;//去重

    for (int i = 0; i < n; i++) {
        while (cnt > 1 && dcmp(Cross(v[cnt - 1] - v[cnt - 2], p[i] - v[cnt - 2])) <= 0) cnt--;
        v[cnt++] = p[i];
    }
    int k = cnt;
    for (int i = n - 2; ~i; --i) {
        while (cnt > k && dcmp(Cross(v[cnt - 1] - v[cnt - 2], p[i] - v[cnt - 2])) <= 0) cnt--;
        v[cnt++] = p[i];
    }
    if (n > 1)  cnt--;
}

int n, m, Acnt, Bcnt;
Point A[maxn], B[maxn], Av[maxn], Bv[maxn];

int main() {
    while (~scanf("%d %d", &n, &m) && (n | m)) {
        for (int i = 0; i < n; i++)
            scanf("%lf %lf", &A[i].x, &A[i].y);
        for (int i = 0; i < m; i++)
            scanf("%lf %lf", &B[i].x, &B[i].y);

        ConvexHull(A, n, Av, Acnt);
        ConvexHull(B, m, Bv, Bcnt);

        bool flag = 0;
        for (int i = 0; i < n; i++)
            if (isPointInPolygon(A[i], Bv, Bcnt) != 0) {
                flag = 1; break;
            }
        for (int i = 0; i < m; i++)
            if (isPointInPolygon(B[i], Av, Acnt) != 0) {
                flag = 1; break;
            }
        if (flag)   goto here;
        for (int i = 0; i < Acnt; i++) {
            Point a1 = Av[i], a2 = Av[(i + 1) % Acnt];
            for (int j = 0; j < Bcnt; j++) {
                Point b1 = Bv[j], b2 = Bv[(j + 1) % Bcnt];
                if (Segment_Proper_Intersection(a1, a2, b1, b2)) {
                    flag = 1; break;
                }
            }
            if (flag)   break;
        }
        here:
        printf("%s\n", flag ? "No" : "Yes");
    }
}

标签:cnt,return,Point,int,凸包,Vector,dcmp,UVa,10256
来源: https://www.cnblogs.com/AlphaWA/p/10964239.html