跳到主要内容

587.安装栅栏

链接:587.安装栅栏
难度:Hard
标签:几何、数组、数学
简介:在一个二维的花园中,有一些用 (x, y) 坐标表示的树。由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树。只有当所有的树都被绳子包围时,花园才能围好栅栏。你需要找到正好位于栅栏边界上的树的坐标。

题解 1 - cpp

  • 编辑时间:2022-04-23
  • 执行用时:32ms
  • 内存消耗:19.3MB
  • 编程语言:cpp
  • 解法介绍:andrew 凸包算法。
class Solution {
public:
int cross(vector<int> &a, vector<int> &b, vector<int> &c) {
int x1 = a[0] - b[0], y1 = a[1] - b[1];
int x2 = c[0] - b[0], y2 = c[1] - b[1];
return x1 * y2 - x2 * y1;
}
vector<vector<int>> outerTrees(vector<vector<int>> &trees) {
int n = trees.size();
if (n <= 3) return trees;
sort(trees.begin(), trees.end(),
[&](vector<int> &a, vector<int> &b) -> bool {
if (a[0] == b[0]) return a[1] < b[1];
return a[0] < b[0];
});
vector<int> list, used(n, 0);
for (int i = 0; i < n; i++) {
while (list.size() > 1 &&
cross(trees[list[list.size() - 2]],
trees[list[list.size() - 1]], trees[i]) < 0) {
used[list.back()] = 0;
list.pop_back();
}
list.push_back(i);
used[i] = 1;
}
int size = list.size();
used[0] = 0;
for (int i = n - 2; i >= 0; i--) {
if (used[i]) continue;
while (list.size() > size &&
cross(trees[list[list.size() - 2]],
trees[list[list.size() - 1]], trees[i]) < 0) {
list.pop_back();
}
list.push_back(i);
}
list.pop_back();
vector<vector<int>> ans;
for (auto &idx : list) ans.emplace_back(trees[idx]);
return ans;
}
};