如何判断一个点 r 在向量 的左边还是右边呢?答案是计算 和 的叉积。
若向量 和向量 的叉积为正,则 r 在 的左边,为负则 r 在 的右边,为0则说明 p、q、r 共线.
叉积计算公式:
即:
1 | int cross(const vector<int> &p, const vector<int> &q, const vector<int> &r) |
那么应当以一种怎样的顺序来考察点集X中的各个点,以判断其是否属于凸包S呢?其实这也就是各种的凸包算法的不同之处。
Andrew的办法是将所有的点按照x坐标从小到大排序,若x坐标相同则按y坐标从小到大排序,设排序后的点集为sortX,按照凸包的定义可以知道x坐标最小的点也就是sortX[0]一定属于凸包。
我们再定义一个栈stack,这个栈里存放目前假定的凸包,自左向右遍历sortX,对取出的每一个点 r,做如下操作:
此番遍历后凸包的下半部分就计算完成了 :
设此时栈中有size个元素,我们再自右向左遍历sortX(最右边的点不用再遍历了),对取出的每一个点 r,做如下操作:
此番遍历后凸包的上半部分就计算完成了:
综上,我们可以写出Andrew算法的代码:
1 | vector<vector<int>> outerTrees(vector<vector<int>>& trees) { |