谈谈我对旋转卡壳算法本质的理解

版权声明:本文为本人原创,允许转载,但转载请注明出处:http://blog.csdn.net/kingpharaoh https://blog.csdn.net/kingpharaoh/article/details/47807901
我学很多东西的过程中,经常无法理解现有的资料的表述,感觉那些讲的太肤浅,最后靠自己推倒证明才能理解,旋转卡壳也是其中的一个……
关于旋转卡壳的资料,大概有这几个:
http://cgm.cs.mcgill.ca/~orm/rotcal.frame.html
http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html
http://www.csie.ntnu.edu.tw/~u91029/ConvexHull.html#a4(如果乱码,注意换一下网页编码)
一些基本概念,如对踵点就不说了,也懒得发图片了,自己画一画就知道了。。


用旋转卡壳最常见的例子:求点对最长距离来说吧,因为最长点对一定是一对对踵点,所以我们可以枚举所有对踵点。
找对踵点的一个超简便方法是找对踵的点和边,为什么可以这样做呢?资料的表述不够清晰:
资料上说“计算这个顶点到该边两个端点的距离,并记录最大的值”,
实际上最后实现中只计算了边的起点到这个边的对踵点的距离,这是为什么呢?
ans=max(ans,max(dist(P[p],P[q]),dist(P[p+1],P[q+1])));


我思考了一下,发现边的本质就是状态转移,
当旋转过程中没有碰到边的时候,“当前对踵点”这个状态始终没有转移,
碰到一个边时,可以按照微分的思想,认为平行线又旋转了无穷小(这是在边不平行的前提下的,边平行时有dist2(ch[p+1],ch[q+1]))
设边(u,v)的对踵点是f(u,v),基于这种思想便可以认为边就是一次由(u,f(u,v))到(v,f(u,v))的状态转移,
也就是说,边是状态转移,状态转移也一定是边,这两者是等价的,


这样就解决了刚开始提出的问题“为什么只需要计算边的起点到这个边的对踵点的距离”,因为这相当于只计算了转移前的状态,
本次转移后的状态一定是某次转移前的状态,而且“某次转移”一定是接下来旋转最先碰到的对面的或相邻的边(转移),
那么我们只需要枚举所有“状态转移”,同时发现f(u,v)是一个单峰函数,
根据单峰函数的性质就可以O(n)时间通过"状态转移"得到所有"状态"了。。


综上所述,这种简便方法的本质是:枚举所有状态转移得到所有状态;
而另一种复杂方法的本质是:给定一个初始状态,进行模拟从而得到所有状态。
阅读更多
换一批

没有更多推荐了,返回首页