内容概要

  一、迷宫问题介绍

  二、栈解决迷宫问题

  三、队列解决迷宫问题 

1、迷宫问题介绍

  迷宫问题简单的说,就是通过一种算法,让计算机找到出口

 

  迷宫可以通过二级列表实现,1表示路不允许通过;0表示路允许通过

    比如下面的二级列表表示的迷宫

maze = [ # 横是y轴,纵是x轴
    [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, 0, 1, 1, 0, 1],
    [1, 1, 0, 1, 1, 1, 1, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 0, 0, 1, 1, 0, 1],
    [1, 0, 1, 1, 1, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]

 

用队列求解迷宫问题java 用队列求解迷宫问题_用队列求解迷宫问题java

  解决迷宫问题有两种思路,一种是使用栈;另一种是使用队列 

2、栈解决迷宫问题

  栈解决迷宫问题,遵照深度优先。

    也就是说一条路走到底,如果没能到达终点或者没有路走,那么就开始回溯,找到另外一条可以走的路。 

  栈解决迷宫问题代码实现

    思路

      (1)规定迷宫,迷宫的起点、终点

      (2)创建栈,栈用于存储相关的路径坐标

      (3)检查栈顶(所在迷宫的当前位置)的四个方向,只要有可通行的节点,将该节点进栈,重复步骤3

      (4)如果四个方向都不能同行,并且没有到达终点,那么是死路,进行回退,栈顶出栈

      (5)重复步骤3(特别要注意的是,想办法识别之前去过的节点,使得不再重复死路)

      (6)找到终点

    需要注意的是:

      (1)如果不存在到达终点的路径,那么栈最终栈会变为空

      (2)回退时,要使锝不再重复去过的路径,可以将去过的路径进行标记,告诉计算机这条路不通

      (3)栈寻路是深度优先,找到的路径并非一定是最短的 

  代码实现

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


def search_path(maze, x1, y1, x2, y2):  # x1, y1是起点坐标;x2, y2是终点坐标
    stack = [(x1, y1)]  # 使用列表充当一个栈,初始存有起点
    while stack:  # 栈空时,说明没有路径
        node = stack[-1]
        if node[0] == x2 and node[1] == y2:  # 查看栈顶是否是终点
            for node in stack:
                print(node)
            break

        for func in li:  # 检查4个方向是否可通过
            next_node = func(node[0], node[1])
            if maze[next_node[0]][next_node[1]] == 0:
                maze[node[0]][node[1]] = 2  # 将前一个节点标记为已走过,避免回到之前的节点,陷入死循环
                stack.append(next_node)  # 更新所在位置
                break
        else:
            maze[node[0]][node[1]] = 2  # 当四个方向都不可通行时,将所在位置设置为无法通行
            stack.pop()  # 回到上一个位置
    else:
        print("没有路径!")


search_path(maze, 1, 1, 8, 8)

 3、队列解决迷宫问题

  队列解决迷宫问题思路

**思路图解**

    自己尝试写的代码(只实现了功能,并且似乎没有使用队列)

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


def search_path(maze, x1, y1, x2, y2):
    nodes = [(x1, y1)]
    maze[x1][y1] = 2
    next_nodes = []
    count = 3
    n = 1

    while len(nodes):
        for node in nodes:
            for func in func_li:
                next_node = func(node[0], node[1])
                if next_node[0] == x2 and next_node[1] == y2:
                    result_node = [next_node]
                    node = next_node
                    # while count > 2:
                    while not (node[0] == x1 and node[1] == y1):
                        for fu in func_li:
                            previous_node = fu(node[0], node[1])
                            if maze[previous_node[0]][previous_node[1]] == count-1:
                                result_node.append(previous_node)
                                node = previous_node
                                count -= 1
                                print(1)
                                break
                            print(result_node)
                    else:
                        # result_node.append((x1, y1))
                        return result_node

                if maze[next_node[0]][next_node[1]] == 0:
                    next_nodes.append(next_node)
                    maze[next_node[0]][next_node[1]] = count

        tmp = nodes
        nodes = next_nodes
        next_nodes = tmp
        next_nodes.clear()
        count += 1
        for li in maze:
            print(li)
        print("=================={}===================".format(n))
        n += 1

    else:
        print("不存在路径!")


re_li = search_path(maze, 1, 1, 8, 8)
print(re_li)

    优化

def search_path(maze, x1, y1, x2, y2):
    nodes = [(x1, y1)]  # 定义一个列表用于存储本次需要探寻的节点
    next_nodes = []  # 将由nodes探寻得到的可通过节点存储到next_nodes中

    maze[x1][y1] = 2  # 将起点设置为已走
    mark = 3  # 动态标记已经走过的节点

    while len(nodes):
        for node in nodes:
            for func in li:
                next_node = func(node[0], node[1])

                # 判断终点和返回路径机制
                if next_node[0] == x2 and next_node[1] == y2:  # 判断节点是否为终点
                    result_node = [next_node]  # 存储最终路径的列表,初始值为终点坐标
                    node = next_node

                    while not (node[0] == x1 and node[1] == y1):  # 这里最难了,找到终点后要进行回溯,从终点节点按照之前设置的动态标记找回起点
                        for fu in li:
                            previous_node = fu(node[0], node[1])
                            if maze[previous_node[0]][previous_node[1]] == mark-1:  # 根据标记找到正确的前一个节点
                                result_node.append(previous_node)
                                node = previous_node
                                mark -= 1  # 下一个标记的值比此次标记值小1
                                break
                    else:
                        result_node.reverse()  # 由于是从终点回退到起点,所以最终的列表循序是反的
                        return result_node

                if maze[next_node[0]][next_node[1]] == 0:  # 判断该节点是否可以通过
                    next_nodes.append(next_node)
                    maze[next_node[0]][next_node[1]] = mark

        tmp = nodes
        nodes = next_nodes
        next_nodes = tmp
        next_nodes.clear()

        mark += 1  # 标记值自增,用于区分不同次的遍历

        # 查看标记
        # for line in maze:
        #     print(line)
        # print()
        
    else:
        print("不存在路径!")

 牛逼的清华大佬的牛逼代码

from collections import deque


def search_path_queue(maze, x1, y1, x2, y2):
    global cur_node
    queue = deque([(x1, y1, -1)])  # 与自己的思路不同的是,大佬将用于找到上一个节点的标记添加每个节点里
    path = []

    while len(queue) > 0:
        node = queue.pop()
        path.append(node)
        for func in li:
            next_node = func(node[0], node[1])

            if maze[next_node[0]][next_node[1]] == 0:
                cur_node = (next_node[0], next_node[1], len(path) - 1)
                queue.append(cur_node)
                maze[next_node[0]][next_node[1]] = 2

            if next_node[0] == x2 and next_node[1] == y2:
                result_li = []
                node = queue.pop()

                while node[2] != -1:
                    result_li.append((node[0], node[1]))
                    node = path[node[2]]
                else:
                    result_li.append((x1, y1))
                    result_li.reverse()
                    return result_li
    else:
        print("没有路径!")