点集子集的最小周长凸包

时间:2010-06-21 18:30:25

标签: algorithm computational-geometry convex-hull

在飞机上给出n个点。 No 3是共线的。

给出数字k。

找到k个点的子集,使得k个点的凸包具有k个点的子集的任何凸包外的最小周长。

我可以想到一个天真的方法在O(n ^ k k log k)中运行。 (找到大小为k的每个子集的凸包,并输出最小值)。

我认为这是一个NP问题,但我找不到任何适合减少的东西。

有人对此问题有任何想法吗?

一个例子,

the set of n=4 points {(0,0), (0,1), (1,0), (2,2)} and k=3

结果:

{(0,0),(0,1),(1,0)}

由于此组包含3个点,因此结果的凸包和周长小于任何其他3个点的结构。

4 个答案:

答案 0 :(得分:9)

这可以在O(kn ^ 3)时间和O(kn ^ 2)空间中完成(如果你想要实际的点,可以在O(kn ^ 3)中完成。)

本文:http://www.win.tue.nl/~gwoegi/papers/area-k-gons.pdf

Eppstein等人提出的算法可以解决这个问题的最小周长和其他权重函数,如面积,内部角度之和等,这些函数遵循一定的约束条件,即使标题表示最小面积(参见周长的推论5.3)。 / p>

基本思想是动态编程方法如下(阅读第4节的前几段):

假设S是给定的点集,Q是具有最小周长的k点的凸包。

令p1为Q的最底点,p2和p3为逆时针顺序的船体上的下一个点。

我们可以将Q分解为三角形p1p2p3和k-1点Q'的凸包(与p1p2p3三角形共用p1p3)。

主要观察结果是Q'对于k-1是最佳的,其中最下面的点是p1并且下一个点是p3并且Q'的所有点位于线p2->的同一侧。 P3。

因此为每个四元组(pi,pj,pk,m)保持4d最佳多边形阵列,以便

  • 多边形是一个恰好m个S点的凸包。
  • pi是多边形的最底部。
  • pj是逆时针顺序的下一个顶点,
  • 多边形的所有点位于线pi的左侧 - > PJ。
  • 所有点都与pi一样位于pj-> pk的同一侧。
在给定m <= k-1的最佳多边形的情况下,

可以帮助我们找到m = k的最佳多边形。

本文详细描述了如何实现这一目标,以达到规定的时空范围。

希望有所帮助。

答案 1 :(得分:2)

这不是一个非常漂亮的解决方案。事实上,实现起来相当痛苦,但它肯定会给出多项式的复杂性。虽然复杂性也很大(n ^ 5 * k是我的粗略估计),但有人可能会找到一种方法来改进它,或者找到一个更好的解决方案。或者对你来说可能就足够了:即使这种复杂性也比暴力强大得多。

注意:带有S的最佳解决方案(设置H)包括来自H内的orignal设置的所有点。否则,我们可以丢弃H的一个边界点并包括那个遗漏点,减少周长 (更新就像'优化' mbeckish 一样)

假设:设置中没有两个点形成一条垂直线。通过围绕坐标原点的一些无理角旋转整组点可以很容易地实现。

由于上述假设,任何复杂的船体都有一个最左边和一个最右边的点。此外,这两点将船体划分为topbottom部分。

现在,让我们从这个船体的top部分和bottom部分中取一个部分。我们将这两个段middle segments和此船体右侧部分的周长称为right周长。
注意:我们需要了解这两个部分,我们需要了解凸包的右侧部分,以便继续将其构建到左侧。但只有两点而不是4点是不够的:我们无法以这种方式维持“凸性”的条件。

导致解决方案。对于每组点{p0,p1,p2,p3}和数字i(i <= k),我们存储可以实现的最小right周长,如果[p0,p1],[p2] ,p3]是两个middle段,i是此解决方案的right部分中的点数(包括其中的点,不仅在边界上)。

我们从右到左遍历所有点。对于每个新点p,我们检查点{p0,p1,p2,p3}的所有组合,使得点p可以将此船体继续向左(在top上或{{1部分)。对于每个这样的集合和大小bottom,我们已经存储了最佳周长大小(参见上面的段落)。

注意:如果您将点i添加到由{p0,p1,p2,p3}点组成的p,您将增加集合大小{{1至少由1.但有时这个数字将是&gt; 1:你必须在三角形{p,p0,p2}中包含所有点。它们不在船体上,而在船体内部。

算法结束了:)此外,尽管可怕的复杂性,您可能会注意到并非所有段[p0,p1],[p2,p3]都可以是right-hull段:它应该大大减少实际计算时间。

更新这仅提供最佳的周边尺寸,而不是设置本身。但是找到这个集很简单:对于上面的每个“状态”,你不仅存储周长大小,还存储最后一点。然后,您可以“追踪”您的解决方案。这是非常标准的技巧,我想这对你来说不是问题,你似乎擅长算法:)

update2 这基本上是DP(动态编程),只是有点臃肿

答案 2 :(得分:1)

一种可能的优化:您可以忽略其凸包含有不在子集中的点的任何子集。

证明:

如果您的凸包含有不在您的子集中的点,则从船体上的子集中移除一个点,并将其替换为船体内部的点。这将产生相等或更小周长的船体。

答案 3 :(得分:-2)

在平面情况下,您可以使用称为Jarvis march的算法,该算法具有最差的案例复杂度O(n ^ 2)。在此算法中,您开始在任意点构建外壳,然后检查下一个需要添加的点。伪代码取自wikipedia

jarvis(S)
   pointOnHull = leftmost point in S
   i = 0
   repeat
      P[i] = pointOnHull
      endpoint = S[0]         // initial endpoint for a candidate edge on the hull
      for j from 1 to |S|-1
         if (S[j] is on left of line from P[i] to endpoint)
            endpoint = S[j]   // found greater left turn, update endpoint
      i = i+1
      pointOnHull = endpoint
   until endpoint == P[0]      // wrapped around to first hull point

据我所知,凸包对每组点都是唯一的,因此无需找到最小值。你只需找到一个,根据定义,它将是最小的一个。

修改

已发布的解决方案解决了具有最少点数的凸包。任何具有更多分数的船体将具有更长的周长,并且我误解了寻求最小周长的问题,而不是具有K点的集合的最小周长。

这个新问题可能是NP所怀疑的,并且最类似于最长的路径问题。不幸的是,我缺乏提供有价值的减少的聪明才智。