这个问题有点牵扯。我编写了一个将simple polygon分解为凸子多边形的算法,但现在我无法证明它不是最优的(即使用 Steiner点的最小凸多边形数< / em>(添加顶点))。我的教授坚持认为不能用这样的贪婪算法来完成,但我想不出一个反例。
所以,如果有人能证明我的算法不是最理想的(或最优的),我将不胜感激。
使用图片解释我的算法的最简单方法(这些是来自较旧的次优版本)
我的算法所做的是将点线周围的线段延伸到相反的边缘上。
如果此范围内没有顶点,则会创建一个新点(红点)并连接到该顶点:
如果 范围内的一个或多个顶点,则它连接到最近的顶点。这个通常产生一个具有最少数量的凸多边形的分解:
但是,在某些情况下它可能会失败 - 在下图中,如果碰巧首先连接中间的绿线,这将创建一个额外的不需要的多边形。为此,我建议仔细检查我们添加的所有边缘(对角线),并检查它们是否仍然是必要的。如果没有,请将其删除:
但在某些情况下,这还不够。见图:
用a-c替换a-b和c-d会产生更好的解决方案。但在这种情况下,没有边缘可以移除,因此这会产生问题。在这种情况下,我建议一个偏好顺序:当决定将反射顶点连接到哪个顶点时,它应该选择具有最高优先级的顶点:
最低)最近的顶点
med)最近的反射顶点
最高)最近的反射,当向后工作时也在范围内(很难解释) -
在this figure中,我们可以看到反射顶点9选择连接到12(因为它最接近),当它连接到5时会更好。两个顶点5和12都在范围内由扩展线段10-9和8-9定义,但顶点5应优先考虑,因为9在4-5和6-5给出的范围内,但不在13-12和11给出的范围内-12。也就是说,边缘9-12在9处消除了反射顶点,但是在12处没有消除反射顶点,但它可以在5处消除反射顶点,因此应优先选择5。
边缘5-12可能仍然存在此修改版本,但可以在后期处理过程中删除。
我有没有错过任何案件?
伪代码(John Feminella要求) - 这是缺少图3和图5中的位
assume vertices in `poly` are given in CCW order
let 'good reflex' (better term??) mean that if poly[i] is being compared with poly[j], then poly[i] is in the range given by the rays poly[j-1], poly[j] and poly[j+1], poly[j]
for each vertex poly[i]
if poly[i] is reflex
find the closest point of intersection given by the ray starting at poly[i-1] and extending in the direction of poly[i] (call this lower bound)
repeat for the ray given by poly[i+1], poly[i] (call this upper bound)
if there are no vertices along boundary of the polygon in the range given by the upper and lower bounds
create a new vertex exactly half way between the lower and upper bound points (lower and upper will lie on the same edge)
connect poly[i] to this new point
else
iterate along the vertices in the range given by the lower and upper bounds, for each vertex poly[j]
if poly[j] is a 'good reflex'
if no other good reflexes have been found
save it (overwrite any other vertex found)
else
if it is closer then the other good reflexes vertices, save it
else
if no good reflexes have been found and it is closer than the other vertices found, save it
connect poly[i] to the best candidate
repeat entire algorithm for both halves of the polygon that was just split
// no reflex vertices found, then `poly` is convex
save poly
原来还有一个我没想到的案例:[图5]
我的算法将尝试将顶点1连接到4,除非我添加另一个检查以确保它可以。因此,我建议使用上面提到的优先级方案将“在范围内”的所有内容填充到优先级队列中,然后取最高优先级,检查它是否可以连接,如果没有,则将其弹出并使用下一个。如果我正确地优化它,我认为这使我的算法O(r n log n)。
我把a website放在一起,松散地描述了我的发现。我倾向于移动东西,所以在它很热的时候拿它。
答案 0 :(得分:2)
我认为常规的五角星(例如,具有共线段的交替点)是你寻求的反例。
编辑以回应评论
根据我修改后的理解,修改后的答案:尝试一个急性五角星(例如一个手臂足够狭窄,只有三个点构成你正在工作的反射点对面的手臂在被认为是“良好的反射点”的范围内。至少在纸上进行处理似乎不仅仅是最优的。但是,对代码的最终读数让我感到疑惑:“最接近”(即最接近什么)是什么意思?
注意强>
即使我的答案被接受,但这不是我们最初想到的反例。正如@Mark在评论中指出的那样,它与最佳值完全相同,从四到五。
触发器,触发器
经过进一步反思,我认为我是对的。通过简单地确保一对臂具有共线边缘,可以将四个的最佳界限保留在锐角中。但算法找到了五个,即使有了补丁。
我明白了:
删除死亡的ImageShack链接
当这是最佳时:
删除死亡的ImageShack链接
答案 1 :(得分:2)
我认为你的算法不是最优的,因为它没有使用任何最优度量。您可以使用其他指标,例如“最近”的顶点,并检查“必要的”对角线。
为了在你的和最佳算法之间驱动一个楔子,我们需要通过寻找具有接近顶点的形状来利用这个间隙,这些形状会严重分解。例如(忽略这些行,我在intertubenet上发现了这一点):
你无法防止最中心点连接到凹面'间隙',即外部到多边形。
你的算法也很复杂,并且可能过度 - 就像复杂的代码一样,你可能会发现它中的错误,因为复杂的代码会产生复杂的假设。
考虑更广泛的初始阶段,将形状分解为更简单的形状(如三角形),然后再使用迭代或遗传算法重新组合它们。你需要一个像这样的阶段来组合凸多边形之间的任何不必要的分割,然后你可能将你可能的分解限制在次优解。
猜测如下:
答案 2 :(得分:1)
但应优先考虑顶点5,因为9在4-5和6-5
给出的范围内
如果4-5和6-5更加凸起,那么你会做什么,以便9不在他们的范围内?然后根据你的规则,正确的做法是连接9到12,因为12是最接近的反射顶点,这将是次优的。
答案 3 :(得分:0)
找到它:(它们实际上非常明显。
* dead imageshack img *
如果允许施泰纳点,四叶三叶草将不是最佳的......红色顶点可能已连接。
* dead imageshack img *
如果没有Steiner积分,它甚至不会是最佳的...... 5可以连接到14,无需3-14,3-12和5-12。这可能是两个多边形更好!哎哟!