Fork me on GitHub

算法之迷宫问题

题目:给一个二维列表,表示迷宫(0表示通道,1表示围墙)。给出算法,求一条走出迷宫的路径。

maze = [
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
 ]

解决思路:

  • 在一个迷宫节点(x,y)上,可以进行四个方向的探查:maze[x-1][y], maze[x+1][y], maze[x][y-1], maze[x][y+1]
  • 思路:从一个节点开始,任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有其他方向的点。
  • 方法:创建一个空栈,首先将入口位置进栈。当栈不空时循环:获取栈顶元素,寻找下一个可走的相邻方块,如果找不到可走的相邻方块,说明当前位置是死胡同,进行回溯(就是讲当前位置出栈,看前面的点是否还有别的出路)

用栈实现:

 

maze = [
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]

dirs = [
    lambda x,y:(x-1,y),  #
    lambda x,y:(x,y+1),  #
    lambda x,y:(x+1,y),  #
    lambda x,y:(x,y-1),  #
]


def solve_maze(x1, y1, x2, y2):
    stack = []
    stack.append((x1,y1))
    maze[x1][y1] = 2
    while len(stack) > 0:   # 当栈不空循环
        cur_node = stack[-1]
        if cur_node == (x2,y2): #到达终点
            for p in stack:
                print(p)
            return True
        for dir in dirs:
            next_node = dir(*cur_node)
            if maze[next_node[0]][next_node[1]] == 0:   #找到一个能走的方向
                stack.append(next_node)
                maze[next_node[0]][next_node[1]] = 2  # 2表示已经走过的点
                break
        else: #如果一个方向也找不到
            stack.pop()
    else:
        print("无路可走")
        return False

 

 

 

用队列实现:

解决思路:

  • 思路:从一个节点开始,寻找所有下面能继续走的点。继续寻找,直到找到出口。
  • 方法:创建一个空队列,将起点位置进队。在队列不为空时循环:出队一次。如果当前位置为出口,则结束算法;否则找出当前方块的4个相邻方块中可走的方块,全部进队。

from collections import deque

maze = [
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]

def solve_maze2(x1,y1,x2,y2):
    queue = deque()
    path = []    # 记录出队之后的节点
    queue.append((x1,y1,-1))
    maze[x1][y1] = 2
    while len(queue) > 0:
        cur_node = queue.popleft()
        path.append(cur_node)
        if cur_node[0] == x2 and cur_node[1] == y2:  #到终点
            real_path = []
            x,y,i = path[-1]
            real_path.append((x,y))
            while i >= 0:
                node = path[i]
                real_path.append(node[0:2])
                i = node[2]
            real_path.reverse()
            for p in real_path:
                print(p)
            return True
        for dir in dirs:
            next_node = dir(cur_node[0], cur_node[1])
            if maze[next_node[0]][next_node[1]] == 0:
                queue.append((next_node[0], next_node[1], len(path)-1))
                maze[next_node[0]][next_node[1]] = 2 # 标记为已经走过
    else:
        print("无路可走")
        return False

solve_maze2(1,1,8,8)

 

posted on 2018-03-03 01:21  vmaze  阅读(232)  评论(0编辑  收藏  举报

导航