用隊列和棧的知識點解決迷宮問題

迷宮問題

這裏有一個迷宮如圖所示,求走出迷宮的路徑node

這裏咱們建一個二維列表,表示迷宮(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]
]

 

用棧解決迷宮問題app

  基本思路:在一個迷宮節點(x,y)上,能夠進行四個方向的探查:maze[x-1][y](表示上), maze[x+1][y](下), maze[x][y-1](左), maze[x][y+1](右)spa

  思路:從一個節點開始,任意找下一個能走的點,當找不到能走的點時,退回上一個點尋找是否有其餘方向的點。code

  方法:建立一個空棧,首先將入口位置進棧。當棧不空時循環:獲取棧頂元素,尋找下一個可走的相鄰方塊,若是找不到可走的相鄰方塊,說明當前位置是死衚衕,進行回溯(就是講當前位置出棧,看前面的點是否還有別的出路)blog

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 stack_solve_maze(x1, y1, x2, y2):
    """
    :param x1: 起點x座標
    :param y1: 起點y座標
    :param x2: 終點x座標
    :param y2: 終點y座標
    :return:
    """
    stack = []
    stack.append((x1,y1))#起點
    maze[x1][y1] = 2#2表示已經走過的點,咱們要將已經走過的點進行標識,省得走重複的路
    while len(stack) > 0:   # 當棧不空循環
        cur_node = stack[-1]#棧頂,即目前所在位置
        if cur_node == (x2,y2): #到達終點
            for p in stack:
                print('==>',p,end='')#依次輸出棧內座標
            return True
        #沒到終點時,在任意位置都要試探上下左右是否走得通
        for dir in dirs:
            next_node = dir(*cur_node)
            if maze[next_node[0]][next_node[1]] == 0:   #0是通道,說明找到一個能走的方向
                stack.append(next_node)
                maze[next_node[0]][next_node[1]] = 2  # 2表示已經走過的點
                break
        else: #若是一個方向也找不到,說明到死衚衕了
            stack.pop()
    else:
        print("無路可走")
        return False


stack_solve_maze(1,1,8,8)
#==> (1, 1)==> (1, 2)==> (2, 2)==> (3, 2)==> (3, 1)==> (4, 1)==> (5, 1)==> (5, 2)==> (5, 3)==> (6, 3)==> (6, 4)==> 
#(6, 5)==> (5, 5)==> (4, 5)==> (4, 6)==> (4, 7)==> (3, 7)==> (3, 8)==> (4, 8)==> (5, 8)==> (6, 8)==> (7, 8)==> (8, 8)

 

用隊列解決迷宮問題隊列

  思路:從一個節點開始,尋找全部下面能繼續走的點。繼續尋找,直到找到出口。內存

  方法:建立一個空隊列,將起點位置進隊。在隊列不爲空時循環:出隊一次。若是當前位置爲出口,則結束算法;不然找出當前方塊的4個相鄰方塊中可走的方塊,所有進隊。io

 

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]
]

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 deque_solve_maze(x1,y1,x2,y2):
    queue = deque()#建立隊列
    path = []    # 記錄出隊以後的節點
    queue.append((x1,y1,-1))
    maze[x1][y1] = 2#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))#將終點座標append到real_path中
            while i >= 0:
                node = path[i]#node是一個元祖(x座標,y座標,該點的leader)
                real_path.append(node[0:2])#只要座標
                i = node[2]
            real_path.reverse()#反轉後順序才爲從起點到終點
            for p in real_path:
                print('==>',p,end='')
            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


deque_solve_maze(1,1,8,8)
#==> (1, 1)==> (2, 1)==> (3, 1)==> (4, 1)==> (5, 1)==> (5, 2)==> (5, 3)==> (6, 3)==> (6, 4)==> 
#(6, 5)==> (7, 5)==> (8, 5)==> (8, 6)==> (8, 7)==> (8, 8)

 

 

 總結class

  棧解決迷宮問題佔用內存相對較小,但用棧找到的出路只是全部出路中的其中一條,具體是哪一條取決於dir列表中上下左右位置定義的順序。

  隊列解決迷宮問題找到的出路確定是最短路徑,可是相對而言用隊列會比較佔用內存。

相關文章
相關標籤/搜索