• 计算几何_凸包


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

    极角排序

    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 
  • 相关阅读:
    文本标记
    第一个HTML文档
    HTML入门
    bootstrap fileinput 文件上传
    DPDK rte_hash 简述
    glib学习笔记-基本知识
    linux常用网络命令
    libevent学习过程
    C语言 singleton模式
    oracle命令行导出、导入dmp文件
  • 原文地址:https://www.cnblogs.com/cgjh/p/9411299.html
Copyright © 2020-2023  润新知