zoukankan      html  css  js  c++  java
  • POJ 1584 A Round Peg in a Ground Hole(凸多边形判断 + 点是否在多边形内 + 点到线段的最短距离)

    题目:传送门

    题意:给你一个圆和一个多边形, 判断多边形是不是凸多边形,如果是,接着判断圆是否在凸多边形内部。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <string>
    #include <math.h>
    
    #define LL long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    using namespace std;
    
    struct Point{
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) { }
    };
    
    const int N = 110;
    const double eps = 1e-8;
    
    int dcmp(double x) {
        if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
    }
    
    Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y); }
    Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y); }
    Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); }
    Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); }
    bool operator == (Point A, Point B) { return dcmp(A.x-B.x) == 0 && dcmp(A.y - B.y) == 0; }
    
    
    double Cross(Point A, Point B) { /// 叉积
        return A.x * B.y - A.y * B.x;
    }
    double Dot(Point A, Point B) {
        return A.x * B.x + A.y * B.y; /// 点积
    }
    double Length(Point A) { return sqrt(Dot(A, A)); }
    
    bool Onseg(Point p, Point a1, Point a2) { /// 判断点 p 是否在线段 a1a2 上(含端点)
        return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) <= 0;
    }
    
    bool SPI(Point a1, Point a2, Point b1, Point b2) { /// 判断线段a1a2与线段b1b2是否相交
        return
        max(a1.x,a2.x) >= min(b1.x,b2.x) &&
        max(b1.x,b2.x) >= min(a1.x,a2.x) &&
        max(a1.y,a2.y) >= min(b1.y,b2.y) &&
        max(b1.y,b2.y) >= min(a1.y,a2.y) &&
        dcmp(Cross(b1 - a2, a1 - a2)) * dcmp(Cross(b2 - a2, a1 - a2)) <= 0 &&
        dcmp(Cross(a1 - b2, b1 - b2)) * dcmp(Cross(a2 - b2, b1 - b2)) <= 0;
    }
    
    inline int isPointInpolygon(Point tmp, Point P[], int n) { /// 判断点是否在多边形里
        int wn = 0;
        rep(i, 0, n - 1) {
            if(Onseg(tmp, P[i], P[(i + 1) % n])) return -1; /// 边界
            int k = dcmp(Cross(P[(i + 1) % n] - P[i], tmp - P[i]));
            int d1 = dcmp(P[i].y - tmp.y);
            int d2 = dcmp(P[(i +1) % n].y - tmp.y);
            if(k > 0 && d1 <= 0 && d2 > 0) wn++;
            if(k < 0 && d2 <= 0 && d1 > 0) wn--;
        }
        if(wn != 0) return 1; /// 内部
        return 0; /// 外部
    }
    /// 判断凸多边形,允许共线,点可以是顺时针给出也可以是逆时针给出,编号0~n-1
    bool isconvex(Point p[], int n) { 
        bool vis[3]; mem(vis, 0);
        rep(i, 0, n - 1) {
            vis[dcmp(Cross(p[(i + 1) % n] - p[i], p[(i + 2) % n] - p[i])) + 1] = 1;
            if(vis[0] && vis[2]) return false;
        }
        return true;
    }
    
    double DistanceToSegment(Point p, Point A, Point B) { /// 求点 p 到线段 AB 的最短距离
        if(A == B) return Length(p - A);
        Point v1 = B - A, v2 = p - A, v3 = p - B;
        if(dcmp(Dot(v1, v2)) < 0) return Length(v2);
        else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);
        else return fabs(Cross(v1, v2)) / Length(v1);
    }
    
    Point P[N];
    
    int main() {
    
        int n;
        double R, x, y;
        while(scanf("%d", &n) == 1) {
            if(n < 3) break;
            scanf("%lf %lf %lf", &R, &x, &y);
            rep(i, 0, n - 1)  scanf("%lf %lf", &P[i].x, &P[i].y);
    
            if(!isconvex(P, n)) { /// 不是凸多边形
                puts("HOLE IS ILL-FORMED");
                continue;
            }
    
            Point p = Point(x, y);
    
            if(isPointInpolygon(p, P, n) == 0) { /// 点不在多边形内部
                puts("PEG WILL NOT FIT");
                continue;
            }
    
            bool flag = 0;
            rep(i, 0, n - 1) { /// 判断点到线段的最短距离是否大于等于 R
                if(dcmp(fabs(DistanceToSegment(p, P[i], P[(i + 1) % n])) - R) < 0) {
                    flag = 1;
                    break;
                }
            }
            if(flag) puts("PEG WILL NOT FIT");
            else puts("PEG WILL FIT");
        }
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    领域驱动和MVVM应用于UWP开发的一些思考
    UWP中实现自定义标题栏
    UWP中新加的数据绑定方式x:Bind分析总结
    MVVM框架从WPF移植到UWP遇到的问题和解决方法
    UWP学习目录整理
    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
    MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信
    MVVM设计模式和WPF中的实现(四)事件绑定
    MVVM模式解析和在WPF中的实现(三)命令绑定
    MVVM模式和在WPF中的实现(二)数据绑定
  • 原文地址:https://www.cnblogs.com/Willems/p/12401486.html
Copyright © 2011-2022 走看看