C ++中的凸包单调链算法
在本教程中,我们将讨论一个程序来查找给定点集的凸包。
凸包是最小的多边形凸图,其中包含图内边界上的所有给定点。
示例
#include <bits/stdc++.h> #define llu long long int using namespace std; //给定点的结构 struct Point { llu x, y; bool operator<(Point p){ return x < p.x || (x == p.x && y < p.y); } }; //计算自制向量的叉积 llu calc_crossproduct(Point O, Point A, Point B){ return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x); } //计算边界上的点 vector<Point> convex_hull(vector<Point> A){ int n = A.size(), k = 0; if (n <= 3) return A; vector<Point> ans(2 * n); //按字典顺序排序的点 sort(A.begin(), A.end()); for (int i = 0; i < n; ++i) { while (k >= 2 && calc_crossproduct(ans[k - 2], ans[k - 1], A[i]) <= 0) k--; ans[k++] = A[i]; } //建造上层船体 for (size_t i = n - 1, t = k + 1; i > 0; --i) { while (k >= t && calc_crossproduct(ans[k - 2], ans[k - 1], A[i - 1]) <= 0) k--; ans[k++] = A[i - 1]; } //调整给定数组的大小 ans.resize(k - 1); return ans; } int main(){ vector<Point> points; points.push_back({ 0, 3 }); points.push_back({ 2, 2 }); points.push_back({ 1, 1 }); points.push_back({ 2, 1 }); points.push_back({ 3, 0 }); points.push_back({ 0, 0 }); points.push_back({ 3, 3 }); vector<Point> ans = convex_hull(points); for (int i = 0; i < ans.size(); i++) cout << "(" << ans[i].x << ", " << ans[i].y << ")" << endl; return 0; }
输出结果
(0, 0) (3, 0) (3, 3) (0, 3)