[转] 求凸包以及距离最远点对
转载自:http://blog.csdn.net/a81895898/article/details/7592156
问题
给定平面上N个点的坐标,找出距离最远的两个点。
分析
类似于“最近点对问题”,这个问题也可以用枚举的方法求解,时间复杂度O(n^2)。
“寻找最近点对”是用到分治策略降低复杂度,而“寻找最远点对”可利用几何性质。注意到:对于平面上有n个点,这一对最远点必然存在于这n个点所构成的一个凸包上(证明略),那么可以排除大量点,如下图所示:
在得到凸包以后,可以只在顶点上面找最远点了。同样,如果不O(n^2)两两枚举,可以想象有两条平行线, “卡”住这个凸包,然后卡紧的情况下旋转一圈,肯定就能找到凸包直径,也就找到了最远的点对。或许这就是为啥叫“旋转卡壳法”。
总结起来,问题解决步骤为:
1、用Graham's Scanning求凸包
2、用Rotating Calipers求凸包直径,也就找到了最远点对。
该算法的平均复杂度为O(nlogn) 。最坏的情况下,如果这n个点本身就构成了一个凸包,时间复杂度为O(n^2)。 旋转卡壳可以用于求凸包的直径、宽度,两个不相交凸包间的最大距离和最小距离等。虽然算法的思想不难理解,但是实现起来真的很容易让人“卡壳”。
逆向思考,如果qa,qb是凸包上最远两点,必然可以分别过qa,qb画出一对平行线。通过旋转这对平行线,我们可以让它和凸包上的一条边重合,如图中蓝色直线,可以注意到,qa是凸包上离p和qb所在直线最远的点。于是我们的思路就是枚举凸包上的所有边,对每一条边找出凸包上离该边最远的顶点,计算这个顶点到该边两个端点的距离,并记录最大的值。直观上这是一个O(n2)的算法,和直接枚举任意两个顶点一样了。但是注意到当我们逆时针枚举边的时候,最远点的变化也是逆时针的,这样就可以不用从头计算最远点,而可以紧接着上一次的最远点继续计算,于是我们得到了O(n)的算法。
POJ 2187 http://poj.org/problem?id=2187