0%

82. 二维凸包(Andrew 安德鲁单调链算法)

题目大意

思路讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
vector<Point> make_convex_hull(vector<Point> A) {
size_t n = A.size();
if (n <= 2) {
// 特判
return A;
}
vector<Point> ans(n * 2);
// Andrew 算法的核心:先按 X 坐标排序,X 相同按 Y 坐标排序
// 这样我们就可以保证处理点的顺序是从左到右
sort(A.begin(), A.end());
int now = -1;
for (int i = 0; i < n; i++) {
// 维护下凸包
// 这个是严格的,不保存共线点的实现
// 只有严格大于 0 的时候才是这个 CCW 的
while (now > 0 && cross(ans[now] - A[i], ans[now - 1] - A[i]) <= 0) {
now--; // 弹出栈顶,因为它会导致凹陷或共线
}
ans[++now] = A[i];
}
int pre = now;
// 从右向左扫描所有点(注意是从 n-2 开始,因为 n-1 已经在栈顶了)
for (int i = n - 2; i >= 0; i--) {
// 维护上凸包
while (now > pre && cross(ans[now] - A[i], ans[now - 1] - A[i]) <= 0) {
now--;
}
ans[++now] = A[i];
}
ans.resize(now);
return ans;
}

AC代码

心路历程(WA,TLE,MLE……)