凸包
二维凸包
定义
凸多边形
凸多边形是指所有内角大小都在 \([0,\pi]\) 范围内的 简单多边形。
凸包
在平面上能包含所有给定点的最小凸多边形叫做凸包。
其定义为:对于给定集合 \(X\),所有包含 \(X\) 的凸集的交集 \(S\) 被称为 \(X\) 的 凸包。
实际上可以理解为用一个橡皮筋包含住所有给定点的形态。
凸包用最小的周长围住了给定的所有点。如果一个凹多边形围住了所有的点,它的周长一定不是最小,如下图。根据三角不等式,凸多边形在周长上一定是最优的。
Andrew 算法求凸包
常用的求法有 Graham 扫描法和 Andrew 算法,这里主要介绍 Andrew 算法。
性质
该算法的时间复杂度为 \(O(n\log n)\),其中 \(n\) 为待求凸包点集的大小,复杂度的瓶颈在于对所有点坐标的双关键字排序。
过程
首先把所有点以横坐标为第一关键字,纵坐标为第二关键字排序。
显然排序后最小的元素和最大的元素一定在凸包上。而且因为是凸多边形,我们如果从一个点出发逆时针走,轨迹总是「左拐」的,一旦出现右拐,就说明这一段不在凸包上。因此我们可以用一个单调栈来维护上下凸壳。
因为从左向右看,上下凸壳所旋转的方向不同,为了让单调栈起作用,我们首先 升序枚举 求出下凸壳,然后 降序 求出上凸壳。
求凸壳时,一旦发现即将进栈的点(\(P\))和栈顶的两个点(\(S_1,S_2\),其中 \(S_1\) 为栈顶)行进的方向向右旋转,即叉积小于 \(0\):\(\overrightarrow{S_2S_1}\times \overrightarrow{S_1P}<0\),则弹出栈顶,回到上一步,继续检测,直到 \(\overrightarrow{S_2S_1}\times \overrightarrow{S_1P}\ge 0\) 或者栈内仅剩一个元素为止。
通常情况下不需要保留位于凸包边上的点,因此上面一段中 \(\overrightarrow{S_2S_1}\times \overrightarrow{S_1P}<0\) 这个条件中的「\(<\)」可以视情况改为 \(\le\),同时后面一个条件应改为 \(>\)。
实现
代码实现
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 |
|
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 |
|
根据上面的代码,最后凸包上有 \(\textit{ans}\) 个元素(额外存储了 \(1\) 号点,因此 \(h\) 数组中有 \(\textit{ans}+1\) 个元素),并且按逆时针方向排序。周长就是
Graham 扫描法
性质
与 Andrew 算法相同,Graham 扫描法的时间复杂度为 \(O(n\log n)\),复杂度瓶颈也在于对所有点排序。
过程
首先找到所有点中,纵坐标最小的一个点 \(P\)。根据凸包的定义我们知道,这个点一定在凸包上。然后将所有的点以相对于点 P 的极角大小为关键字进行排序。
和 Andrew 算法类似地,我们考虑从点 \(P\) 出发,在凸包上逆时针走,那么我们经过的所有节点一定都是「左拐」的。形式化地说,对于凸包逆时针方向上任意连续经过的三个点 \(P_1, P_2, P_3\),一定满足 \(\overrightarrow{P_1 P_2} \times \overrightarrow{P_2 P_3} \ge 0\)。
新建一个栈用于存储凸包的信息,先将 \(P\) 压入栈中,然后按照极角序依次尝试加入每一个点。如果进栈的点 \(P_0\) 和栈顶的两个点 \(P_1, P_2\)(其中 \(P_1\) 为栈顶)行进的方向「右拐」了,那么就弹出栈顶的 \(P_1\),不断重复上述过程直至进栈的点与栈顶的两个点满足条件,或者栈中仅剩下一个元素,再将 \(P_0\) 压入栈中。
代码实现
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 33 34 35 36 37 38 39 |
|
三维凸包
基础知识
圆的反演:反演中心为 \(O\),反演半径为 \(R\),若经过 \(O\) 的直线经过 \(P\),\(P'\),且 \(OP\times OP'=R^{2}\),则称 \(P\)、\(P'\) 关于 \(O\) 互为反演。
过程
求凸包的过程如下:
- 首先对其微小扰动,避免出现四点共面的情况。
- 对于一个已知凸包,新增一个点 \(P\),将 \(P\) 视作一个点光源,向凸包做射线,可以知道,光线的可见面和不可见面一定是由若干条棱隔开的。
- 将光的可见面删去,并新增由其分割棱与 \(P\) 构成的平面。 重复此过程即可,由 Pick 定理、欧拉公式(在凸多面体中,其顶点 \(V\)、边数 \(E\) 及面数 \(F\) 满足 \(V−E+F=2\))和圆的反演,复杂度 \(O(n^2)\)。1
模板题
重复上述过程即可得到答案。
代码实现
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
|
练习
参考资料与注释
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用