我有几个形式的笛卡尔点:(x,y)
其中x和y都是非负整数。
例如 (0,0),(1,1),(0,1)
我需要一个算法来安排以上几点 以这种方式从一个点到另一个点 将x或y更改为1.
换句话说,我想避免 对角线运动。
因此,上述各点的安排如下:
(0,0),(0,1),(1,1)。
类似于(0,0),(1,1),(0,2)
没有这样的安排。
我不知道该怎么称呼它 但我会称之为曼哈顿订购。
有人可以帮忙吗?
答案 0 :(得分:12)
如果您正在寻找不重复顶点的排列:
你似乎在寻找网格图中的汉密尔顿路径。
对于一般网格图,已知这是NP-Complete,请参阅Hamilton Paths in Grid Graphs。
所以你可以试试运气哈密顿路径/欧几里德旅行商问题的任何近似/启发式/等算法。
如果您正在寻找可以重复的安排,但希望在安排中尽可能少的点数:
这又是NP-Complete。上述问题可以减少到它。这是因为当且仅当图形具有哈密尔顿路径时,最小可能步行具有n个顶点。
如果您只是寻找一些积分,
然后您需要做的就是检查图表是否已连接。如果没有连接,就没有这样的安排。
你可以进行深度优先搜索来计算出来。深度优先搜索还可以在连接图形时为您提供这样的安排。
如果你想要更接近最优的东西(但是在相当快的时间内),你可以使用近似算法来解决欧几里德旅行商问题。
答案 1 :(得分:4)
您可以构建一个图形,顶点是您的点,边缘是有效的步骤。
您正在寻找的是此图表的Hamiltonian path。这在一般形式中是NP完全问题,这意味着没有已知的有效解决方案(即,与点数一起很好地扩展的解决方案)。维基百科描述了randomized algorithm在大多数图表上“快速”并且可能有用:
从随机顶点开始,如果没有访问过的邻居,则继续。如果没有更多未访问的邻居,并且形成的路径不是哈密顿量,则随机均匀地选择邻居,并使用该邻居作为枢轴进行旋转。 (也就是说,为该邻居添加一条边,并从该邻居中删除一条现有边,以便不形成循环。)然后,在路径的新端继续算法。
但是,对于这种特殊情况,可能存在更有效的解决方案。
答案 2 :(得分:2)
将其视为一个图表,其中每个节点最多为四个边。然后进行深度/广度优先搜索。
答案 3 :(得分:1)
这可以简化为最小化每个连续点之间的距离。从(0,0)到(0,1)只是1个单位,但从(0,0)到(1,1)实际上是sqrt(2)。因此,如果您将点排列成图形,然后执行简单的最小总距离遍历(旅行推销员),则应正确排列它们。
编辑:如果你从不想要一个大于1的步骤,只需添加任何大于1的边。遍历仍然可以正常工作,并忽略任何需要移动的路径> 1。
编辑2:为了进一步说明,您可以使用任何您想要的边缘选择算法。如果您可以移动2个空格,只要空间不是对角线,那么您可以选择在(0,2)和(0,4)之间放置一条边。最小距离算法仍然有效。只需以聪明的方式放置边缘,您就可以使用任意数量的选择标准来确定结果。
答案 4 :(得分:0)
执行此操作的一种方法是创建两个已排序的坐标列表。一个按x排序,一个按y排序。然后,递归地找到解决方案。
代码来了(不知道还有什么语言;可能是伪代码?)...编辑 - 没关系,因为我的答案不如其他一些人好。
答案 5 :(得分:0)
蛮力递归REXX例程怎么样...尽可能尝试 路径和打印出来的那些。
/* rexx */
point. = 0 /* Boolean for each existing point */
say 'Enter origin x and y coordinate:'
pull xo yo
point.xo.yo = 1 /* Point exists... */
say 'Enter destination x and y coordinate:'
pull xd yd
point.xd.yd = 1 /* Point exists... */
say 'Enter remaining x and y coordinates, one pair per line:'
do forever
pull x y
if x = '' then leave
point.x.y = 1
end
path = ''
call findpath xo yo path
say 'All possible paths have been displayed'
return
findpath: procedure expose point. xd yd
arg x y path
if \point.x.y then return /* no such point */
newpoint = '(' || x y || ')'
if pos(newpoint, path) > 0 then return /* abandon on cycle */
if x = xd & y = yd then /* found a path */
say path newpoint
else do /* keep searching */
call findpath x+1 y path newpoint
call findpath x-1 y path newpoint
call findpath x y+1 path newpoint
call findpath x y-1 path newpoint
end
return
示例会话:
Path.rex
Enter origin x and y coordinate:
0 0
Enter destination x and y coordinate:
2 2
Enter remaining x and y coordinates, one pair per line:
0 1
1 1
2 1
1 2
(0 0) (0 1) (1 1) (2 1) (2 2)
(0 0) (0 1) (1 1) (1 2) (2 2)
All possible paths have been displayed
不要尝试任何大的东西 - 可能需要很长时间!但后来这个问题从未提及任何关于成为最佳解决方案的问题。