zoukankan      html  css  js  c++  java
  • 计算几何_凸包

    极角排序求凸包      水平排序求凸包

    极角排序

    struct Point {
        double x, y;
        Point () {}
        Point (double _x, double _y) : x(_x), y(_y) {}
        
        Point operator + (const Point &a) const { return Point(x + a.x, y + a.y); }
        
        // 叉积=0是指两向量平行(重合)
        Point operator - (const Point &a) const { return Point(x - a.x, y - a.y); }
        
        double operator ^ (const Point &a) const { return x * a.y - y * a.x; }  // 叉积 
        double operator * (const Point &a) const { return x * a.x + y * a.y; }  // 点积 
        
        // 定义给map set 之类用的.. 不要用极角 可能会出错 
        bool operator <  (const Point &a) const {
            if (x != a.x) return x < a.x;
            return y < a.y;
        }
    };
    
    double GetCross(Point st, Point ed1, Point ed2) { return (ed1 - st) ^ (ed2 - st); }
    
    //  叉积极角排序 
    //  直接把原点当作 极点  进行 极角排序. 
    bool cmp_j_j(const Point &A, const Point &B) {  
        if ((A ^ B) != 0.0) return (A ^ B) > 0.0;
        if (A.x != B.x)  return A.x < B.x;
        return A.y < B.y;
    }
    
    //  叉积极角排序. 
    //  以Qcmppt为起点 做极角排序. 
    Point Qcmppt; 
    bool cmp_j_j_j(const Point &A, const Point &B) {  
        int m = (A-Qcmppt) ^ (B-Qcmppt);
        if (m != 0.0) return m > 0.0;
        if (A.x != B.x)  return A.x < B.x;
        return false;
    }
    
    //  atan2 极角排序
    //  atan2 赛高  听说速度快些 但是精度比叉积差些  听说,.,, 未实践 
    bool cmp_o_o(const Point &A, const Point &B) { 
        if (atan2(A.y, A.x) != atan2(B.y, B.x)) return atan2(A.y, A.x) < atan2(B.y, B.x);
        if (A.x != B.x)  return A.x < B.x;
        return A.y < B.y;
    }
    
    // ---------------------------------------------------------
    // 凸包 极角排序   不能用于共线点
    // 要把第一个点(最左下角的点)放在最前面 而且sort的时候不包含进去.
    // 该点是起点 
    for (i=1; i<=n; ++i) {
        scanf("%lf%lf", &pt[i].x, &pt[i].y);
        pt[i].flag = false;
        if (pt[i].y < pt[1].y)  swap(pt[i], pt[1]);
        else if (pt[i].y == pt[1].y && pt[i].x < pt[1].x) swap(pt[i], pt[1]);
    } 
    Qcmppt = pt[1]; // Qcmppt 全局变量 
    sort(pt+2, pt+1+m+n, cmp_j_j_j);   // 排序方法也可以用 atan2 排序 cmp_o_o() 
    head = 0;
    for (i=1; i<=n; ++i) {
        while  (head>1 && GetCross(pt[st[head-1]], pt[st[head]], pt[i]) <= 0.0) head--;
        st[++head] = i;
    }
    // head 就是点的个数 

    水平排序求凸包

    struct Point {
        double x, y;
        Point () {}
        Point (double _x, double _y) : x(_x), y(_y) {}
        
        Point operator + (const Point &a) const { return Point(x + a.x, y + a.y); }
        
        // 叉积=0是指两向量平行(重合)
        Point operator - (const Point &a) const { return Point(x - a.x, y - a.y); }
        
        double operator ^ (const Point &a) const { return x * a.y - y * a.x; }  // 叉积 
        double operator * (const Point &a) const { return x * a.x + y * a.y; }  // 点积 
        
        // 定义给map set 之类用的.. 不要用极角 可能会出错 
        bool operator <  (const Point &a) const {
            if (x != a.x) return x < a.x;
            return y < a.y;
        }
    };
    
    double GetCross(Point st, Point ed1, Point ed2) { return (ed1 - st) ^ (ed2 - st); }
    
    // 凸包  水平排序 允许有重点
    // 点从1到n 
    sort(pt+1, pt+n+1, cmp_s_p);
    head = 0;
    for (i=1; i<=n; ++i) {
        // 如果 不希望 有"三点共线", 重点 把 下面的 两个 < 都改成 <= 
        while  (head>1 && GetCross(pt[st[head-1]], pt[st[head]], pt[i]) < 0.0) head--;
        st[++head] = i;
    }
    int t = head;
    for (i=n-1; i>=1; --i) { // 注意是n-1 
        while  (head>=t && GetCross(pt[st[head-1]], pt[st[head]], pt[i]) < 0.0) head--;  // 貌似head>=t  不然wa....原理嘛...不是很懂.
        st[++head] = i;
    } 
    // 答案会把起点包含2次 所以看情况 head减1 
  • 相关阅读:
    300. Longest Increasing Subsequence_算法有误
    LIS (DP)_代码
    pthread_detach pthread_create实例
    pthread_detach
    DP(动态规划)
    括号匹配(二)
    gdb调试遇到的问题
    matplotlib 显示中文
    一个奇怪的编码 big5-hkscs
    python 重载 __hash__ __eq__
  • 原文地址:https://www.cnblogs.com/cgjh/p/9411299.html
Copyright © 2011-2022 走看看