凸包问题:礼品包装算法
凸包(Convex Hull)是一个计算几何(图形学)中的概念。
在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。
X的凸包可以用X内所有点(X1,…Xn)的线性组合来构造.
在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。
例子:假设平面上有p0~p11共11个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候,我们就叫它“凸包”。
Gift Wrapping
时间复杂度:O(n㏒n)
思路:Gift Wrapping思想是先找到凸包上的一个点,然后从那个点开始按逆时针方向逐个找凸包上的点,实际上就是进行极角排序,然后对其查询使用。
步骤:
把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,令其为P0。
以 P0 作为原点, 计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前面。由几何知识可以知道,排序后第一个点 P1 和最后一个点 Pn 一定是凸包上的点。
(以上是准备步骤,以下开始求凸包)
以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在栈里面。现在从步骤3求得的那个结果里,把 P1 后面的那个点拿出来做当前点,即 P2 。那么P2是否有可能为凸包上的点呢,首先连接P0和栈顶点P1,得到x向量 L ,连接P1和P2得向量L1,
看L与L1的叉积是否大于零,
(1):大于零这将P2入栈,继续选取P3为当前点,重复以上步骤,
(2)否则说明当前栈顶点不是凸包上的点,将栈顶元素 ,继续选取P3为当前点,重复以上步骤,
最后,栈中的元素就是凸包上的点了。
附上代码(Java 实现)