温馨提示:本文翻译自stackoverflow.com,查看原文请点击:algorithm - Connecting a set of points with horizontally aligned polylines without them crossing
algorithm language-agnostic path-finding robotics

algorithm - 将一组点与水平对齐的多段线连接而不会交叉

发布于 2020-06-28 03:26:07

我已经尝试解决这个问题几天了,但是我找不到一个好的解决方案。

我有一组2D点,其中所有值都是整数。没有一点是相同的。我想在所有点上绘制折线/路径/任何内容,但有一些限制:

1:一条线应始终沿正x方向移动。p1.x <p2.x <...

2:线可能永远不会交叉。

3:所有折线必须以x = 0开始,以x-max结尾。

4:应使用尽可能少的折线(或由我定义的数字)。

I have attached an image of a sample set of points. And a hand made solution I drew with a pencil and ruler.

It's trivial to find a solution by hand, but I have no idea how to describe my process in logical terms. I don't need an optimal solution (whatever that means). It doesn't need to be fast.

Point set (Disregard colors)

Connected Points

My current solution is to step through the set along the x-axis and then try all viable combinations and choosing the one with the lowest total vertical movement. This works in some cases but not all. And it seems to over-complicate the problem.

My next idea is to do a brute force approach with backtracking when collisions occour. But that also seems a bit much.

对于任何想知道这些要点实际上是乐谱上的笔记的人。x轴是时间,y轴是音高。折线代表机械手弹钢琴的动作。

查看更多

提问者
Hermasetas
被浏览
24
CodeChef 2020-04-06 10:13

我们将找到一种使用最少数量的机械手指(最少数量的折线)的解决方案。诀窍是将您的输入视为部分排序的集(或位姿)。输入中的每个点都是位姿的元素,并且当且仅当p1.x <p2.x时,关系(p1.x,p1.y)<(p2.x,p2.y)。这基本上意味着具有相同x坐标的两个点是不可比的。

现在,让我们忘记这个约束:“线可能永远不会交叉”。最后,我们将继续讨论。

您正在寻找的是将这个摆放器划分成多个链条。这是使用Dilworth定理完成应该清楚的是,如果有5个点具有相同的x坐标,那么我们至少需要5条不同的折线。迪尔沃思的意思是,如果没有x坐标的点超过5个点,那么我们可以获得5条覆盖所有点的折线(链)。而且,它还为我们提供了一种找到这些折线的方法,我在这里总结一下:

您只需创建一个二部图G =(U,V,E),其中U = V =所有输入点的集合,并且如果ux <vx,则(u,v)是G中的边,然后找到最大匹配项 M此图,并考虑在M中存在边(u,v)时,通过在同一折线上包含u和v形成的折线集合。

现在唯一的问题是,其中某些折线可能会相互交叉。我们将看到如何解决该问题:

首先,让我们假设只有两条折线L1和L2。您找到它们相交的第一个实例(最小x坐标)。假设彼此交叉的两个线段是AB和CD:

穿越

我们删除AB和CD,而添加AD和CB:

穿越延迟

折线仍相互交叉,但其交叉点已延迟。因此,我们可以继续重复此过程,直到没有交叉为止。这最多需要n次迭代。因此,我们知道如何“解缠”两条折线。

[位于段CD上的B的边缘情况也以完全相同的方式处理]

现在,假设我们有k条不同的折线,最大匹配已赋予我们这些折线:L1,L2,...,Lk。WLOG,让我们假设在x = 0时,L1的y坐标低于L2的y坐标,后者低于L3的y坐标,依此类推。

取L1并查找它第一次与任何其他折线交叉。在那个交叉处,应用上述交换操作。继续重复此操作,直到L1不与任何其他折线交叉。现在,L1位于“底部”,并且不与其他任何线交叉。现在,我们将L1输出为最终折线之一,并将其​​从算法中删除。然后,我们对L2重复相同的过程,输出后,将其删除,然后对L3重复,依此类推。