在n * m网格中找到所有可能的步行而不重复

时间:2017-05-16 23:50:35

标签: python algorithm

我想通过尺寸为n*m的网格找到所有可能的步行路线,其中步行不能多次使用节点,并且允许移动到相邻节点(包括对角线)。

例如,1*1网格是微不足道的;只有一次步行,即[(0,0)]1*2网格有4个可能的行走点,即[(0,0)][(0,1)][(0,0),(0,1)][(0,1),(0,0)]2*2网格有4个无关紧要的行程1,[(0,0)][(0,1)][(1,0)][(1,1)],12行{2} {{1} },[(0,0), (0,1)][(0,0),(1,0)]等,16行长度3([(0,0),(1,1)]等)和16行长度4([(0,0),(0,1),(1,1)]等)。

这是我尝试在python中实现递归算法以列出n * m网格中的所有可能的步行,但它没有返回正确的解决方案。我通过迭代所有起点接近它,然后形成一个可能的后续步骤的递归树。

[(0,0),(0,1),(1,1),(1,0)]

对于我的代码无法正常工作或者更好的解决此问题的方法的任何帮助都非常感谢。谢谢!

2 个答案:

答案 0 :(得分:0)

我添加了一些跟踪工具。从(0,0)开始的输出低于该值。打印语句根据级别缩进,我只是在一些有用的位置打印出当前位置。

代码:

dim=(2,2)
walks=[]
indent = ""

def main():
    for row in range(dim[0]):
        for col in range(dim[1]):
            walked=[[False for i in range(dim[0])] for j in range(dim[1])]
            walkTree(row, col, walked, [])

    for dist in range(1, dim[0]*dim[1]+1):
        print "length", dist, "\n\t", [path for path in walks if len(path) == dist]

def walkTree(row, col, walked, leading):
    global indent
    print indent, "ENTER", "pos", row, col, "walked=", walked, "lead=", leading
    indent += "  "
    walks.append( leading+[(row,col)] )
    walked[row][col] = True
    leading.append((row,col))

    print indent, "ROW-", row, col, walked
    if row-1 >= 0:
        if col-1 >= 0:
            if not walked[row-1][col-1]:
                walkTree(row-1, col-1, walked, leading)
        if not walked[row-1][col]:
                walkTree(row-1, col, walked, leading)
        if col+1 < dim[1]:
            if not walked[row-1][col+1]:
                walkTree(row-1, col+1, walked, leading)

    print indent, "COL-", row, col, walked
    if col-1 >= 0:
        if not walked[row][col-1]:
            walkTree(row, col-1, walked, leading)

    print indent, "COL+", row, col, walked
    if col+1 < dim[1]:
        if not walked[row][col+1]:
            walkTree(row, col+1, walked, leading)

    print indent, "ROW+", row, col, walked
    if row+1 < dim[0]:
        if col-1 >= 0:
            if not walked[row+1][col-1]:
                walkTree(row+1, col-1, walked, leading)
        if not walked[row+1][col]:
                walkTree(row+1, col, walked, leading)
        if col+1 < dim[1]:
            if not walked[row+1][col+1]:
                walkTree(row+1, col+1, walked, leading)

    indent = indent[2:]

在输出中(我只打印前1/4),请注意如何从(0,0)起点仅覆盖一条线性路径:步进(0,1),然后(1,0) ,最后(1,1)。但是,当您从每个步骤返回时,您无法涵盖任何其他选项,例如移动(0,0)=&gt; (0,1)=&gt; (1,1)从那里到(1,0)。

致命的缺陷是,当您回溯时,您不会管理您的状态列表。在下面显示的情况下,当你回溯到(0,0)时,你仍然将整个网格标记为 walked 。相反,尝试重置代码:在从例程返回之前,

walked[row,col] = False

...或制作walked的本地副本,而不是处理本质上是全局主列表的内容。

我已经将leading的处理留给了你,现在你有了提示。

输出:

 ENTER pos 0 0 walked= [[False, False], [False, False]] lead= []
   ROW- 0 0 [[True, False], [False, False]]
   COL- 0 0 [[True, False], [False, False]]
   COL+ 0 0 [[True, False], [False, False]]
   ENTER pos 0 1 walked= [[True, False], [False, False]] lead= [(0, 0)]
     ROW- 0 1 [[True, True], [False, False]]
     COL- 0 1 [[True, True], [False, False]]
     COL+ 0 1 [[True, True], [False, False]]
     ROW+ 0 1 [[True, True], [False, False]]
     ENTER pos 1 0 walked= [[True, True], [False, False]] lead= [(0, 0), (0, 1)]
       ROW- 1 0 [[True, True], [True, False]]
       COL- 1 0 [[True, True], [True, False]]
       COL+ 1 0 [[True, True], [True, False]]
       ENTER pos 1 1 walked= [[True, True], [True, False]] lead= [(0, 0), (0, 1), (1, 0)]
         ROW- 1 1 [[True, True], [True, True]]
         COL- 1 1 [[True, True], [True, True]]
         COL+ 1 1 [[True, True], [True, True]]
         ROW+ 1 1 [[True, True], [True, True]]
       ROW+ 1 0 [[True, True], [True, True]]
   ROW+ 0 0 [[True, True], [True, True]]
 ENTER pos 0 1 walked= [[False, False], [False, False]] lead= []
   ROW- 0 1 [[False, True], [False, False]]
   COL- 0 1 [[False, True], [False, False]]
 ...

答案 1 :(得分:0)

还有另一种方法。您可以将问题减少到图形上的已知问题,然后使用图形库来解决它。

  1. 将单元格定义为节点,将所有相邻单元格(包括对角线)与边缘连接。

  2. 添加另外两个节点s和d。将s连接到所有初始节点,对d执行相同操作。

  3. 然后您的问题变为:找到s和d之间的所有简单路径。用于python的networkx库可以做到这一点(参见https://networkx.readthedocs.io/en/stable/reference/generated/networkx.algorithms.simple_paths.all_simple_paths.html),因此igraph可以用于R(它会更快地完成)。由于一些奇怪的原因,igraph中的igraph似乎没有类似的功能。