第六章---计算几何

文章目录

    • 六、计算几何
      • [6.1 基础几何模板](#6.1 基础几何模板)
      • [6.2 点到线段距离 / 线段相交](#6.2 点到线段距离 / 线段相交)
      • [6.3 凸包(Andrew 算法)](#6.3 凸包(Andrew 算法))

六、计算几何

6.1 基础几何模板

cpp 复制代码
class Solver {
public:
    const double eps = 1e-8;
    const double PI = acos(-1.0);
    int sign(double x) {
        if (fabs(x) < eps) return 0;
        return x < 0 ? -1 : 1;
    }
    struct Point {
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) {}
        Point operator+(Point b) { return Point(x + b.x, y + b.y); }
        Point operator-(Point b) { return Point(x - b.x, y - b.y); }
        Point operator*(double k) { return Point(x * k, y * k); }
        double operator*(Point b) { return x * b.x + y * b.y; }  // 点积
        double operator^(Point b) { return x * b.y - y * b.x; }  // 叉积
        double len() { return sqrt(x*x + y*y); }
        double len2() { return x*x + y*y; }
    };
    // 叉积:ab × ac
    double cross(Point a, Point b, Point c) {
        return (b - a) ^ (c - a);
    }
    // 点积:ab · ac
    double dot(Point a, Point b, Point c) {
        return (b - a) * (c - a);
    }
    // 两点距离
    double dist(Point a, Point b) {
        return (a - b).len();
    }
};

思路要点:

  • 点积:判断夹角(锐角/钝角/垂直)、投影长度
  • 叉积:判断转向(顺/逆时针)、平行四边形面积
  • 浮点比较用 sign 函数,避免精度问题

6.2 点到线段距离 / 线段相交

cpp 复制代码
class Solver {
public:
    // 点p到线段ab的距离
    double point_to_seg(Point p, Point a, Point b) {
        if (sign(dot(a, b, p)) < 0) return dist(p, a);
        if (sign(dot(b, a, p)) < 0) return dist(p, b);
        return fabs(cross(a, b, p)) / dist(a, b);
    }
    // 判断线段相交(规范相交)
    bool seg_intersect(Point a1, Point a2, Point b1, Point b2) {
        double c1 = cross(a1, a2, b1), c2 = cross(a1, a2, b2);
        double c3 = cross(b1, b2, a1), c4 = cross(b1, b2, a2);
        return sign(c1) * sign(c2) < 0 && sign(c3) * sign(c4) < 0;
    }
};

6.3 凸包(Andrew 算法)

cpp 复制代码
class Andrew {
public:
    vector<Point> convex_hull(vector<Point> p) {
        int n = p.size(), k = 0;
        if (n <= 1) return p;
        sort(p.begin(), p.end(), [](Point a, Point b) {
            return sign(a.x - b.x) ? a.x < b.x : a.y < b.y;
        });
        vector<Point> res(n * 2);
        // 下凸壳
        for (int i = 0; i < n; res[k++] = p[i++])
            while (k >= 2 && sign(cross(res[k-2], res[k-1], p[i])) <= 0) k--;
        // 上凸壳
        for (int i = n - 2, t = k + 1; i >= 0; res[k++] = p[i--])
            while (k >= t && sign(cross(res[k-2], res[k-1], p[i])) <= 0) k--;
        res.resize(k - 1);
        return res;
    }
};

思路要点:

  • 按 x 排序,x 相同按 y
  • 从左到右扫下凸壳,右到左扫上凸壳
  • 栈内维护凸性,不满足则弹出
  • 时间复杂度 O(n log n)

相关推荐
minglie11 小时前
Visual Studio问题
学习
其实防守也摸鱼1 小时前
存储管理:页面置换算法学习任务(测验题要求给出置换页面顺序,缺页次数,缺页率)
android·前端·数据库·学习·oracle·自动化
ss2731 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 12 PostgreSQL数据目录与重要文件结构
数据库·笔记·postgresql
dadaobusi1 小时前
学习: gdb自动捕获调用栈
学习
Song_RsHt1 小时前
Gateway (上):路由与转发,微服务的统一入口
java·笔记·后端·学习·gateway
2603_969579281 小时前
备份云盘是什么意思?简单说就是“用云盘来备份数据”
学习
骑士雄师2 小时前
《结构化思维》第五章 · 精读回顾(案例版 · 含结构图)
笔记
Logic1012 小时前
C语言/数据结构二维数组题解:找出行列O个数均为偶数的格子——奇偶性预处理+二次遍历
c语言·数据结构·算法·二维数组·时间复杂度·动态内存分配·奇偶性
程序猿阿森2 小时前
【机器学习实战】朴素贝叶斯算法详解:从概率基础到商品评论情感分析
算法·机器学习·概率论