您的位置:首页 > 其它

旋转卡壳--凸包的直径

2011-09-23 12:55 183 查看

凸包的直径

例题:

poj 2187 直接求直径OK

凸包的直径

多边形的直径被定义为多边形上任意两点间的最大距离的值。 在多边形上,决定直径的点可能不止一对。 事实上,如果一个多边形含有n个顶点,那么就最多有 n 对“直径点对”在。



上图所示的是一个简单的多边形直径的实例。 直径点对在图中是被平行的切线(用红色表示)穿过的黑点. 直径是用淡蓝色高亮表示的。
很明显, 确定凸多边形 P 直径的点对不可能在多边形 P 内部。 所以搜索应该在边界上进行。 事实上, 由于直径是多边形的平行切线的最远距离, 所以我们只需要查询对踵点。 Shamos (1978) 提供了一个 简单的 时间复杂度为O(n) 的计算凸包对踵点对的算法。这个算法是通过遍历这些点的列表, 得到最大距离即直径,然后输出这个点对。 下面是Shamos 算法的伪代码,1985年在
Preparata 和 Shamos 文章中进行发表。

输入是一个多边形 P={p1,...,pn}

begin
p0:=pn;
q:=NEXT[p];
while (Area(p,NEXT[p],NEXT[q]) > Area(p,NEXT[p],q)) do
q:=NEXT[q];
q0:=q;
while (q != p0) do
begin
p:=NEXT[p];
Print(p,q);
while (Area(p,NEXT[p],NEXT[q]) > Area(p,NEXT[p],q) do
begin
q:=NEXT[q];
if ((p,q) != (q0,p0)) then Print(p,q)
else return
end;
if (Area(p,NEXT[p],NEXT[q]) = Area(p,NEXT[p],q)) then
if ((p,q) != (q0,p0)) then Print(p,NEXT[q])
else Print(NEXT[p],q)
end
end.


注意 Print(p,q) 表示将 (p,q) 作为一个对踵点对输出, Area(p,q,r) 表示三角形 pqr 的有向面积。
虽然直觉看这个过程与常规旋转卡壳算法不同, 但从本质上看是相同的, 并且避免了任何角度的计算。
下面试是一个比较直观的算法:

1、计算出多边形 y 方向上的端点。 设为 ymin 和 ymax 。

2、通过 ymin 和 ymax 构造两条水平切线。 由于他们已经是一对对踵点, 计算他们之间的距离并维护为一个当前最大值。

3、同时旋转两条线直到其中一条与多边形的一条边重合。

4、一对新的对踵点对此时产生。 计算新的距离, 并和当前最大值比较, 大于当前最大值则更新。

5、重复步骤3和步骤4的过程直到再次产生对踵点对 (ymin,ymax) 。

6、输出确定最大直径的对踵点对。

虽然上述的过程(给出的伪代码)变得非常有用, 但是我们仍可以从对踵点对中得到其他的信息, 如多边形的宽度 。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: