首页 关于
树枝想去撕裂天空 / 却只戳了几个微小的窟窿 / 它透出天外的光亮 / 人们把它叫做月亮和星星
目录

4.5 随机增量算法
(Randomized Incremental Algorithm)

我们已经描述了一个 \(O(n \log n)\) 的最优算法和一个 \(O(n^2)\) 的实用算法。人们自然会问,是否存在一个实用的 \(O(n \log n)\) 的算法? 这不仅仅是一个学术问题。 有些应用需要重复计算许多点的凸包,例如,在由复杂多面体模型组成的环境中进行碰撞检测。幸运的是,Clarkson & Shor(1989) 提出了一种随机算法, 能够达到 \(O(n \log n)\) 的期望时间。回顾第 2.4.1 节,这意味着该算法在任何输入上都能以高概率达到这种时间复杂度。

我们在这里简要概述该算法,它是增量算法的一个变体。初看之下,它似乎比原算法更差。回想一下算法 4.1, 我们通过计算点 \(p_i\) 和每个面 \(f\) 确定的四面体的体积来寻找,下一个要添加的点 \(p_i\) 所能见到的面 \(H_{i-1}\)。这种复杂度为 \(O(n)\) 的检查被执行了 \(O(n)\) 次,最终的复杂度为 \(O(n^2)\)。 为了确定哪些面可见,Clarkson-Shor 算法避免了对所有面进行蛮力搜索。它通过一个数据结构,冲突图(conflict graph),来维护两组互补信息来实现。

这似乎破坏了增量算法的纯粹,增量算法一次只处理一个点。但这部分额外信息使得寻找可见面变得容易。因为当添加 \(p_i\) 时,它可以看到的面集合,即与它"冲突"的面,可以直接从冲突图中获得。

每次迭代都需要更新冲突图。移除关于已删除面的信息很容易。唯一困难的部分是,添加与 \(p_i\) 相关联的新锥面的信息。设 \(f = \text{conv}\{e, p_i\}\) 是一个基于多胞体边缘 \(e\) 的面。 该边缘位于从 \(p_i\) 可见和不可见的面之间的边界上。如果 \(p_k\) 能看到 \(f\),那么它至少能够看到 \(H_{i-1}\) 中与 \(e\) 相邻的两个面中的一个,如图4.10 和图 4.11所示。

虽然这给出了如何在每次迭代中更新冲突图的提示,但整体复杂度是否得到改善一点也不清楚。这需要微妙的分析才能得到 \(O(n \log n)\) 的期望复杂度。 参见 Mulmuley (1994, Sec. 3.2) 或 de Berg, et al. (1997, Sec. 11.2)。幸运的是,这种微妙的分析并没有使算法本身变得更加复杂。

4.5.1. 练习 (Exercises)

  1. 冲突更新Conflict updates。证明上述命题,即如果 \(p_k\) 能看见 \(f = \text{conv} \{e, p_i\}\), 那么它必然能看见与 \(e\) 相邻的两个面中的至少一个,或两个。利用这一点详细说明一种高效的更新过程。
  2. [Programming] 实现Implementation。修改 chull.c 以维护一个冲突图。对其进行测试,并观察 \(n \approx 10^5\) 时,搜索量的减少是否能弥补图更新的开销。



Copyright @ 高乙超. All Rights Reserved. 京ICP备16033081号-1