1. 向量叉积
定义cross(p,q,r)如下:
若cross(p,q,r)>0,则方向经过逆时针旋转小于180°得到方向,若cross(p,q,r)<0,则方向经过顺时针旋转小于180°得到方向,若cross(p,q,r)=0,与同向或反向。
2. Graham算法
3. 例题
class Solution {
public:
double cross(const vector<int>& p, const vector<int>& q, const vector<int>& r) {
double x1 = q[0] - p[0], y1 = q[1] - p[1];
double x2 = r[0] - q[0], y2 = r[1] - q[1];
return x1 * y2 - y1 * x2;
}
double dis(const vector<int>& a, const vector<int>& b) {
return pow(a[0] - b[0], 2) + pow(a[1] - b[1], 2);
}
vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
if (trees.size() <= 3)
return trees;
int n = trees.size();
int ind = 0;
for (int i = 0; i < n; i++)
if (trees[i][0] < trees[ind][0] || trees[i][0] == trees[ind][0] && trees[i][1] < trees[ind][1]) {
ind = i;
}
swap(trees[0], trees[ind]);
sort(trees.begin() + 1, trees.end(), [&](const vector<int>& a, const vector<int>& b) {
if (cross(trees[0], a, b) != 0)
return cross(trees[0], a, b) > 0;
else
return dis(trees[0], a) < dis(trees[0], b);
});
int l = n - 1;
while (l >= 0 && cross(trees[0], trees[n - 1], trees[l]) == 0)
l--;
for (int left = l + 1, right = n - 1; left < right; left++, right--) {
swap(trees[left], trees[right]);
}
vector<vector<int>> ans{ trees[0],trees[1] };
for (int i = 2; i < n; i++) {
while (ans.size() >= 2 && cross(ans[ans.size() - 2], ans[ans.size() - 1], trees[i]) < 0)
ans.pop_back();
ans.push_back(trees[i]);
}
return ans;
}
};