在本教程中,我们将讨论一个程序来查找给定点集的凸包。
凸包是最小的多边形凸图,其中包含图内边界上的所有给定点。
#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)