Skip to content

算法Algorithm

旋转卡壳与凸多边形直径

Rotating calipers diameter algorithm

沿凸多边形的支撑方向单调推进对踵点,枚举足够的候选对并在线性时间求出最远距离。

形式陈述 ​

固定实平面的标准 Euclidean 内积。已知一个凸多边形的逆时针极点序列 p0,…,ph−1,怎样求

diam(P)=maxx,y∈P‖x−y‖2

而不枚举全部顶点对?最大值可在顶点对取得:固定一个点,距离作为另一变量的凸函数,在有限凸组合上不超过某个顶点的距离;两边依次换成顶点即可。因此对任意有限点集,先求其凸包,再对极点序列计算直径。

称两个顶点为对踵点,如果存在两条平行支撑线分别经过它们,并把多边形夹在中间。任意最远点对都是对踵点:垂直于连线的两个支撑方向必须在这两端达到极值,否则还有一点在该方向上更远,从而 Euclidean 距离也更大。

对每条有向边 pipi+1,定义不除边长的高度

Ai(j)=orient(pi,pi+1,pj).

它是三角形有向面积的两倍。先令 j=1:对首边 p0p1,从它自身的终点开始沿高度上升方向寻找第一个最高点;后续边沿用前一边得到的 j。具体地,只要 Ai(j+1)>Ai(j) 就前进。停止后比较 (pi,pj) 和 (pi+1,pj) 的距离;若下一点等高,还要比较它与两个边端点的组合。下标按 h 循环,平局时不能只留一个方向的候选。

直觉

两条平行尺贴在凸多边形外面。旋转它们时,接触点沿边界按同一个方向走,不会倒退。一个支撑方向在一条边的法向处发生事件;此刻至少一把尺贴住整条边,另一把尺落在一个顶点或另一条平行边上。

所有需要考虑的对踵顶点对都出现在这些接触变化附近。因此每条边只需要看它对面的最高点,并把边的两个端点都纳入距离比较。最高点最大化的是到直线的垂距,不是到某个固定端点的距离,所以最后这一步不能省略。

支撑事件与最远点对
例子与边界

取逆时针六边形

(−1,3),(0,0),(4,0),(6,2),(4,5),(1,6).

分别编号 0,…,5。随着边 i=0,1,…,5 前进,对面最高点的编号可以依次取

3,5,5,1,1,3.

这里 5→1 是跨过编号零继续向前,不是指针退回。把循环序列展开后,每次支撑接触都沿同一方向移动。

第一条边 p0p1 的对面点为 p3=(6,2)。两个候选平方距离为

‖p0−p3‖2=72+(−1)2=50,‖p1−p3‖2=62+22=40.

其余边事件都没有超过 50,所以直径为 50。穷举全部十五对顶点也给出相同结果。核验程序使用平方距离比较,直到输出长度时才开平方,避免无关的浮点舍入。

矩形体现平局边界。一条边的对面也是一整条平行边,两个对面端点等高,真正的直径却是对角线。如果算法在等高时只比较任意一个端点组合,可能漏掉另一条最大对角线,甚至因候选实现不完整而漏掉最大值。实现要么显式枚举平行边的四种端点配对,要么证明其等价平局处理覆盖这些候选。

输入若有连续共线点,先压成真正极点可简化支撑接触;若还要返回所有达到最大值的原输入索引,再用保留的边界映射恢复。全共线点集的凸包是一条线段,答案直接是两端距离;单点和空集应有自己的接口,不能硬进入循环卡壳。

推论与应用

凸性使对面接触单调前进。按上述首边初始化后,初始化和整圈推进合计不超过常数倍 h 次;每条边还做常数次平局比较。用摊还分析,整个阶段时间为 O(h)、额外空间 O(1),输出全部平局点对时另计输出大小。

若原输入是 n 个无序点,端到端成本还包括凸包构造;不能把 O(h) 卡壳阶段写成任意点集的线性直径算法。所有面积比较可由精确方向谓词完成,整型坐标的平方距离可能比原坐标需要更多位数。

最近点对依靠局部稀疏条带,而直径由凸包边界与全局支撑控制。旋转卡壳也可用于宽度或最小包围矩形,但目标函数和需要同步的支撑线数量会改变;“都能旋转”不是这些算法共享同一候选公式的理由。

参考资料
关系图谱11 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系