旋转卡壳算法总结

一、历史背景

1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生。当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来确定。 
后来直径演化为由一对对踵点对来确定。 Shamos提出了一个简单的 O(n) 时间的算法来确定一个凸 n 角形的对踵点对。 因为他们最多只有 3n/2 对, 直径可以在 O(n) 时间内算出。 
如同Toussaint后来提出的, Shamos的算法就像绕着多边形旋转一对卡壳。 因此就有了术语“旋转卡壳”。 1983年, Toussaint发表了一篇论文, 其中用同样的技术来解决许多问题。 从此, 基于此模型的新算法就确立了, 解决了许多问题。 

这就是旋转卡壳!

二、应用

  • 计算距离
    • 凸多边形直径
    • 凸多边形宽
    • 凸多边形间最大距离
    • 凸多边形间最小距离
  • 外接矩形
    • 最小面积外接矩形
    • 最小周长外接矩形
  • 三角剖分
    • 洋葱三角剖分
    • 螺旋三角剖分
    • 四边形剖分
  • 凸多边形属性
    • 合并凸包
    • 找共切线
    • 凸多边形交
    • 临界切线
    • 凸多边形矢量和
  • 最薄截面
    • 最薄横截带

三、定理证明

1. 点集中最远的两个点一定出现在凸包的顶点上

证明:任取凸包内部两点,总能把连线延长至凸包边界处得到更远的两点,之后对于边界上的两点又可以移动到顶点处得到更远的两点。也就是说在求最大距离时凸包内部两点会被顶点两点覆盖掉。

2. 凸包直径 = 最大对踵点对距离 = 点集中两顶点最大距离

左半部分证明:凸包直径是距离最远的两条平行凸多边形切线,对踵点对是卡住凸多边形两侧切线的切点对。首先要知道在两切线旋转出最大距离时的对踵点对连线一定垂直两平行切线,若不垂直则旋转至垂直最优,若旋转至垂直后无法保证对踵点对不变则说明直径变大了,这与前提矛盾。之后可知凸包直径一定是某对对踵点对的距离,同时可以反证出其一定为最远的那对对踵点。

右半部分证明:同样用反证法,假设最远对踵点对不是距离最远的两点,那说明还存在距离更大的两点,垂直这两点连线作凸多边形两切线可得到更远的对踵点对,与前提矛盾。

3. 点集中构成面积最大的三角形时三个顶点一定出现在凸包的顶点上

证明:若三角形三个顶点在凸包内部则可以将顶点分别平移至凸包边界上,此时得到面积更大的三角形,之后任取一边为底边,可以把剩余的一个顶点平移至该边的切点位置,这样可以进一步扩大三角形面积,对每条边进行同样处理可以发现最终三个顶点都位于凸包顶点处。也就是说任意的凸包内部三角形都可以找到一个比它大的且顶点都在凸包顶点上的三角形来覆盖,因此得出结论。

4. 点集中构成面积最大的n边形时其n个顶点一定出现在凸包的顶点上

证明:由于要求面积最大,那么这个n边形一定是凸多边形,不会是凹多边形(凹多边形求凸包会得到面积更大边数更少的凸多边形),在凸包内部任取一个n边形都能把n个顶点平移至凸包边界上,之后类似上面那条结论的证明可以将n个顶点移动到凸包顶点位置来获得更大的n边形,得证。

5. 存在一对平行边的四边形其max(两条对角线长) > max(两斜边长)

证明:这是比较显然的,可以分两种情况+勾股定理证明。

6. 最小矩形覆盖一定有一条边与凸包上一条边重合

证明:略。

7. 凸包宽度 = 每条边到最远点距离的最小值

证明:首先要知道凸包宽度的定义,凸包宽度是任意两条平行切线距离的最小值,另外还有一个结论,对于任意的“点-点”的两条切线,总可以通过旋转得到距离更小的“点-边”切线或“边-边”切线。因此只需要枚举每条边,取所有边到其最远点距离的最小值。

四、模板

旋转卡壳实际上就是在枚举每对对踵点(凸包不存在平行边时,若存在可以忽略掉某些对踵点对),由于对踵点对数量级为n所以算法的时间复杂度也为O(n)。另外实际应用时要考虑一些细节,比如凸包上存在两条平行边的情况,顶点数组访问时处理越界情况等。

	int ans = 0;
	for(int i = 0, j = 1; i < con.n; i++)//p[i]与p[j]构成对踵点对
	{
		while(((a.p[i+1]-a.p[i])^(a.p[j]-a.p[i])) < ((a.p[i+1]-a.p[i])^(a.p[j+1]-a.p[i])))
			j++;
		ans = max(ans, int((a.p[j]-a.p[i]).len2()));
	}

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值