使用c++写一个简洁高效的凸包算法,带注释
时间: 2024-03-15 10:47:15 浏览: 57
好的,以下是一个常用的 Graham 扫描算法的实现,使用 C++ 语言编写,并带有注释。注释中会标注每个变量的含义和作用,方便理解。
```cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
struct Point {
int x, y;
} p[N], s[N]; // p 表示输入的点集,s 表示凸包上的点集
int n, top; // n 表示输入点集的大小,top 表示凸包上的点的个数
// 计算两点之间的距离
int dis(Point a, Point b) {
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
// 计算两个向量的叉积
int cross(Point a, Point b, Point c) {
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
// 比较两个点的极角,用于排序
bool cmp(Point a, Point b) {
int c = cross(p[1], a, b);
if (c > 0) return true;
if (c == 0 && dis(p[1], a) < dis(p[1], b)) return true;
return false;
}
// Graham 扫描算法
void Graham() {
// 找到基准点,这里选择纵坐标最小的点
int k = 1;
for (int i = 2; i <= n; i++) {
if (p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) {
k = i;
}
}
// 将基准点放在数组第一位
swap(p[1], p[k]);
// 按照极角排序,排序结果存放在 p 数组中
sort(p + 2, p + n + 1, cmp);
// 进行 Graham 扫描
top = 2;
s[1] = p[1], s[2] = p[2];
for (int i = 3; i <= n; i++) {
while (top > 1 && cross(s[top - 1], s[top], p[i]) <= 0) {
top--;
}
s[++top] = p[i];
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
}
Graham();
// 输出凸包上的点
for (int i = 1; i <= top; i++) {
printf("%d %d\n", s[i].x, s[i].y);
}
return 0;
}
```
以上就是一个简洁高效的 Graham 扫描算法的实现,希望能够帮助您。
阅读全文