寻找迷宫的最短解决方案或最长解决方案

时间:2019-01-26 15:46:37

标签: python algorithm graph-algorithm maze

我正在做一个作业,在该作业中我已经解决了主要问题并正在研究扩展练习。目前,已经给出了一张地图,并在网格上标识了所有可能的迷宫解决方案,网格的打印方式如下:

    1 1 3 1 0 2 
    3 3 3 3 1 3 
    3 3 1 3 3 3 
    3 3 3 1 3 0 
    3 1 3 1 3 1 
    3 1 3 3 3 0 

其中0是空白空间,1是墙壁,2是目标,3是访问空间。扩展任务是在任何给定的起点下,为迷宫提供最短的解决方案。如果起点是一堵墙,那么迷宫就无法解决。这也很好。它应该能够为给定的任何迷宫工作。

我真的不知道从哪里开始这个问题。一个想法是取所有路径的总和并找到其中的最小路径,但是我不确定如何实现这一点。

当前这是我的代码:

EMPTY = 0
WALL = 1
GOAL = 2
VISITED = 3


def solve(grid, x, y):
    if grid[x][y] == GOAL:
        show_grid(grid)
        return True
    elif grid[x][y] == WALL:
        return False
    elif grid[x][y] == VISITED:
        return False
    else:
       # mark as visited
       grid[x][y] = VISITED

       # explore neighbors clockwise starting by going up
       if      ((x < len(grid)-1  and solve(grid, x + 1, y))
             or (y > 0            and solve(grid, x, y-1))
             or (x > 0            and solve(grid, x-1, y))
             or (y < len(grid)-1  and solve(grid, x, y+1))):
           return True
       else:
           return False


def show_grid (grid):
    for i in range(len(grid), 0, -1):
        # print("i: ", i)
        for element in grid[i-1]:
            print (element, end=" ")
        print()


def main ():
    grid =    [[EMPTY, WALL, EMPTY, EMPTY, EMPTY, EMPTY],
               [EMPTY, WALL, EMPTY, WALL, EMPTY, WALL],
               [EMPTY, EMPTY, EMPTY, WALL, EMPTY, EMPTY],
               [EMPTY, EMPTY, WALL, EMPTY, EMPTY, EMPTY],
               [EMPTY, EMPTY, EMPTY, EMPTY, WALL, EMPTY],
               [WALL, WALL, EMPTY, WALL, EMPTY, GOAL]]

    solve(grid, 0, 0)

扩展名要求打印最短路径的长度,其中遍历1平方等于1个移动。感谢您提供有关此问题的任何帮助。

2 个答案:

答案 0 :(得分:1)

您正在使用递归浏览网格,其中的基本情况是找到了GOALsolve的每个实例仅返回一个布尔值,因此您丢失了信息-实例采用的路径。

重构,以便该函数在可行时返回网格位置,并累积实例后代的返回值。

您需要重新考虑您的条件,并且您想确保探索所有路径(上,下,左,右)。在条件bool((0,0)) -> True中使用a tuple is evaluated True这一事实可能会有所帮助。

最后您可以:

  • 积累所有成功的路径,然后确定完成该过程时的最小和最大长度或
  • 评估处理中的成功路径长度 ,并使用placeholder(?)变量保持当前的最大和最小-此选项会丢弃路径信息,但是如果您不需要没关系。

我试图根据您当前的代码来制定该代码,因为我假设您了解当前流程的工作方式,并且从那里开始可能会更容易。

您还可以将网格查看为图形,每个 point 是一个节点,该节点的边缘与其周围的节点相邻。您可以先将网格解析为图形,然后使用任何定义良好的算法遍历图形并找到答案。对于树解决方案,根将是搜索的起点。我没有很多使用图的经验,所以我觉得我无法为此提供详细的答案-也许有人会给出更好的解释。 / p>

答案 1 :(得分:1)

我同意@wwii的回答,如果您正在探索所有解决方案,只需返回每个成功路径的长度,然后找到最短的路径即可。可以通过以下更改来实现:

  1. 更改已解决的函数以返回路径,而不是true或false。
  2. 在每个节点上,而不是将3用于访问,可以将从该节点到解决方案(或原点)的最小长度放入,将-1和1放入不能到达解决方案的墙和节点。无法到达解决方案的节点本质上是墙壁。

例如,

GOAL = 'G'
WALL = 'W'
EMPTY = 'E'


def solve(grid, x, y):
    if grid[x][y] == WALL or grid[x][y].endswith(GOAL):
        return grid[x][y]

    candidates = []
    # explore neighbors clockwise starting by going down
    if x < len(grid)-1:
        candidates.append('d' + solve(grid, x + 1, y))
    if y > 0:
        candidates.append('l' + solve(grid, x, y - 1))
    if x > 0:
        candidates.append('u' + solve(grid, x - 1, y))
    if y < len(grid)-1:
        candidates.append('r' + solve(grid, x, y + 1))

    # get rid of none solutions from candidates
    candidates = [x for x in candidates if not x.endswith(GOAL)]
    if not candidates: # if no solution, it's essentially a wall
        grid[x][y] = 'W'
    else: 
        # getting shortest path
        grid[x][y] = sorted(candidates, key=lambda x: len(x))[0]

        # for longest path use code below instead of above
        # grid[x][y] = sorted(candidates, key=lambda x: len(x))[-1]
    return grid[x][y]

如果访问了某个节点并到达了目标,则该节点上的值可能类似于“ drrurG”。这意味着最短的路径是向下,向右* 2,向上,向右,目标。方向约定向下表示向下一行,即x + 1。

请确保您可能需要更改代码的其他部分才能起作用。


令人回味的食物

以上代码遍历了所有可能的路径。但是您可能不需要。到达最短路径的方法可能更快,因为此问题并不像其他一般的寻路问题那么复杂。

例如,绝对最短的路径显然是从起点到目标的直线。首先检查。如果这不是解决方案,请开始检查下一条最短路径。看看那些工作。如果没有,继续前进直到找到它。