0%

计算几何(三)

凸包基础

定义

凸多边形

所有内角大小都在 $[0,\pi]$ 范围内的简单多边形。

凸包

在平面上能包含所有给定点的最小凸多边形。

可以理解为用一个橡皮筋包含住所有给定点的形态。

性质:凸包用最小的周长围住了所有点。

极点

凸包的顶点

性质:若点 P 是点集 S 的一个极点,那么存在一条经过点 P 的直线 l,使得点集 S 中除了 P 的所有点都在 l 的同一侧。

极边

凸包的边

性质:点集中除了极边上的点外都在极边所在直线的同一侧。

求凸包

极点法

枚举每个点,判断每个点是否是极点。

依据:将凸包以凸包内一点为顶点进行三角剖分,非极点一定落在某个三角形内部,枚举另外三个点组成三角形,若点落在了某个三角形内部,则它不是极点。

时间复杂度:$O(n^4)$。

极边法

枚举两点组成的边,判断它是否是极边。

依据:其它点在极边所在直线的同一侧。

时间复杂度:$O(n^3)$。

增量法

每次用一个点去更新凸包。

  • 若点在凸包内,舍弃
  • 若点在凸包外,找凸包的切线

可推广至三维凸包、动态凸包。

判断点在凸包内:$n$ 次 to-left 测试。$O(n)$。

找凸包的切线:前驱和后继都在射线的同一侧。暴力 $O(n)$。

时间复杂度:$O(n^2)$。

判断点在凸包内和找凸包的切线均存在 $O(n\log n)$ 做法。

Gift wrapping

从一条极边出发遍历其它点找到下一条极边。

时间复杂度:$O(nh)$,最坏 $O(n^2)$,$h$ 表示凸包的极点数。

起点的确定:

点集中最左/右/上/下的点一定是凸包的极点(若最左/右/上/下的点不唯一,则是极边上的点,此时取另一个方向上坐标最大/小的点)。

Graham scan

基于极角排序的求凸包算法。

算法流程:

  • 以最左下角的点为极点,进行极角排序。
  • 将极点与极点的下一个点入栈。
  • 对于要入栈的下一个点,如果从栈顶连向该点需要顺时针旋转,则弹出栈顶。
  • 重复 3,直到从栈顶连向该点需要逆时针旋转。
  • 将下一个点入栈,回到 3。

时间复杂度:$O(n\log n)$。瓶颈为极角排序。

Andrew’s algorithm

基于横坐标(x)排序的求凸包算法。

以最左最右两点为界,凸包可以分为上凸包和下凸包两部分。

算法流程:

  • 对点集以横坐标(x)为第一关键字,纵坐标(y)为第二关键字排序。
  • 正序遍历每个点,用栈维护下凸包。
  • 倒序遍历每个点,用栈维护上凸包。

栈的维护方式与 Graham scan 一致。

时间复杂度:$O(n\log n)$。瓶颈为排序。