点集子集的最小周长凸包
Posted
技术标签:
【中文标题】点集子集的最小周长凸包【英文标题】:The minimum perimeter convex hull of a subset of a point set 【发布时间】:2011-03-06 11:13:25 【问题描述】:给定平面上的 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 个点的集合。
【问题讨论】:
您可能想为那些不知道从哪里开始学习凸包和计算几何,但可能想改进算法的人发布代码或伪代码。 是否会使用以点之间的距离作为权重的 MST 以某种方式简化问题?至少在某些情况下,我可以想到它如何让事情变得更容易一些(但我也可以想到它可能不是很有用的情况)。 我想知道 Voronoi 图是否有助于解决这个问题。因为这会给你所有最近的邻居到一个点,我希望你至少要为你测试的每个点少迭代几个点。 (哦,当然 MST 意味着您已经知道最近的邻居) 你能举一个例子说明一组点有多个可能的凸包吗?越想越觉得这是不可能的情况。 @MikeD 一组 n 个点只有一个外壳,但是这些点中的 k这可以在 O(kn^3) 时间和 O(kn^2) 空间内完成(或者如果您想要实际点数,也可以在 O(kn^3) 内完成)。
本文:http://www.win.tue.nl/~gwoegi/papers/area-k-gons.pdf
Eppstein 等人的算法可以解决最小周长和其他权重函数(如面积、内角总和等)的问题,这些函数遵循一定的约束条件,即使标题说的是最小面积(周长参见推论 5.3)。
基本思想是如下动态规划方法(阅读第 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 数组,使得
多边形是 S 的 m 个点的凸包。 pi 是多边形的最底部点。 pj 是逆时针顺序的下一个顶点, 多边形的所有点都位于线 pi -> pj 的左侧。 所有点都位于 pj->pk 的同一侧,就像 pi 一样。可以帮助我们找到 m=k 的最佳多边形,给定 m
该论文准确地描述了如何去做,以实现规定的空间和时间界限。
希望对您有所帮助。
【讨论】:
该论文参考了在 O(n log n + k4n) 中找到最小周长 k 边形,如果 k 远小于 n,这可能是有意义的。跨度> 又是你 :D 你是怎么找到所有这些论文的? 你又来了:D!你是怎么找到这么好的问题的? ;-) @Mgccl。对不起,我没有真正回答你的问题。我不确定我是怎么想到这个的。这是昨晚很晚了,我忘记了! (很抱歉没有再次回答您的问题) 白痴又来了。好问题,好答案和伪代码启动!【参考方案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,并且与最长路径问题最相似。不幸的是,我缺乏提供有价值的减少的聪明才智。
【讨论】:
这为您提供了一个凸包算法 - 他正在尝试(我认为)从 N 中 K 的包最小的点中找到最佳子集 K。这只会生成一个外壳 - 但从我的阅读来看,它并没有回答“真正的”问题。 但这就是问题所在:他想知道一种算法来找到哪些点集为指定数量的点提供了最小的凸包。 看到“convex hull”这个词后,您是否有机会停止阅读这个问题?【参考方案3】:这不是一个很好的解决方案。事实上,实现起来相当痛苦,但它肯定会产生多项式复杂性。虽然复杂性也很大(n^5*k 是我的粗略估计),但有人可能会找到改进它的方法或在这里找到更好解决方案的想法。或者它可能对你来说就足够了:即使这种复杂性也比暴力破解要好得多。
注意:带有船体H
的最优解(集合S
)包括来自H
内部原始集合的所有点。否则,我们可以丢弃H
的边界点之一并包含该丢失的点,从而减小周长。
(更新就像发布的“优化”mbeckish)
假设:集合中没有两点形成一条垂直线。可以通过围绕坐标原点将整组点旋转一些不合理的角度来轻松实现。
由于上述假设,任何复杂的船体都有一个最左边和一个最右边的点。另外,这两点将船体分为top
和bottom
部分。
现在,让我们从船体的top
部分截取一段,从bottom
部分截取一段。让我们将这两个部分称为 middle segments
和该船体右侧部分的周长 - right
perimeter。注意:这两个部分是我们需要了解的关于凸面右侧部分的全部信息船体继续向左建造。但是只有两点而不是四点是不够的:我们不能以这种方式维持“凸”的条件。
它会导致解决方案。对于每组点 p0, p1, p2, p3 和数字 i
(i right 周长,如果 [p0, p1], [p2, p3] 是两个则可以实现middle
段和i
是该解决方案的right
部分中的点数(包括其中的点,不仅在边界上)。
我们从右到左遍历所有点。对于每个新点 p
,我们检查点 p0, p1, p2, p3 的所有组合,以便点 p 可以将这个外壳继续向左(在 top
或 bottom
部分上)。对于每个这样的集合和大小i
,我们已经存储了最佳周长大小(参见上面的段落)。
注意:如果您将点 p
添加到由点 p0, p1, p2, p3 组成的 right-hull
,您将至少将集合大小 i
增加 1 . 但有时这个数字会大于 1:你必须包括三角形 p, p0, p2 中的所有点。它们不在船体上,而是在船体内部。
算法结束 :) 此外,尽管复杂性令人恐惧,但您可能会注意到并非所有段 [p0, p1], [p2, p3] 都可以是middle
段:它应该会大大减少实际计算时间。
更新这仅提供最佳周长尺寸,而不是集合本身。但是找到集合很简单:对于上面的每个“状态”,您不仅存储周长大小,还存储最后添加的点。然后,您可以“追溯”您的解决方案。这是相当标准的技巧,我想这对你来说不是问题,你似乎擅长算法:)
update2这本质上是DP(动态编程),只是有点臃肿
【讨论】:
喜欢整体方法 - DP 方法似乎是要走的路。此外,蛮力方法应该具有复杂性 C(n,k) (not n^k) klog(k) 对于 k @Nikita Rybak:我不确定我是否完全明白你在这里描述的内容,所以如果我可以要求澄清一个特定点:如果凸包具有最小周界,这将如何工作长度是三角形吗? @andand k=3 是“简化”这个算法的最糟糕的方法:它基本上归结为尝试三点的所有组合。我建议先熟悉 DP:它是一种非常通用的技术,可以帮助您解决许多不同的问题。 @Nikita Rybak Refreing to "rotating the entire set of points by some irrational angle" ...例如 2*PI :) @Beta:我并不想简化问题。我的意思是,我看不到您的算法将如何将三角形凸包视为潜在的解决方案。如果实际解决方案是三角形,您的算法将如何检测它?【参考方案4】:一种可能的优化:您可以忽略其凸包包含不在子集中的点的任何子集。
证明:
如果您的凸包包含不在您的子集中的点,则从您的子集中删除一个位于包上的点,并将其替换为包内部的一个点。这将产生一个周长相等或更小的船体。
【讨论】:
这在实践中究竟如何运作?为了忽略这些子集,你必须计算它们的凸包(或者至少找出它们的凸包是否包含不在子集中的点),所以你实际上并没有忽略它们。 另外,如果你用一个在船体内部的船体点替换一个船体点,新船体不一定是凸的。因此,当您重新生成凸包时,它可能不包括内部点,并且您将拥有一个少于 K 个点的凸包。考虑一个五边形凸包,其中心有一个额外的内部点。用该中心点替换任何顶点,生成的多边形将不是凸的。 @A. Levy - 当你重新生成凸包时,新选择的点需要在凸包上或里面,否则你重新生成的凸包不正确。 @IVlad - 这个想法是,一旦您找到一个具有额外内部点的凸包,您就可以使用该知识提前修剪其他一些点排列。例如,考虑 k = 30,并假设某个子集产生一个凸包,该凸包上有 3 个点,以及额外的内部点。您现在可以消除船体上 3 个点的所有排列以及船体外部可能的数千个点,因为任何这样的子集都会产生一个包含原始船体的船体,因此应该被忽略。 通过“您现在可以消除外壳上 3 个点的所有排列以及外壳外可能的数千个点”,我的意思是任何包含原始凸包上 3 个点的子集,加上凸包外部点集合中的 k-3 个其他点。以上是关于点集子集的最小周长凸包的主要内容,如果未能解决你的问题,请参考以下文章
(hdu step 7.1.7)Wall(求凸包的周长——求将全部点围起来的最小凸多边形的周长)
(hdu step 7.1.7)Wall(求凸包的周长——求将全部点围起来的最小凸多边形的周长)