棧和隊列的應用——迷宮問題

給一個二維列表,表示迷宮(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]
      ]
#封裝一個列表表示四個位置表達式
dirs=[
      lambda x,y:(x+1,y),
      lambda x,y:(x-1,y),
      lambda x,y:(x,y-1),
      lambda x,y:(x,y+1)
      ]
def maze_path(x1,y1,x2,y2):#x1,y1表示起點位置,x2,y2表示終點位置
    stack=[]#空棧
    stack.append((x1,y1))
    while(len(stack)>0):#當棧不空時
        curNode=stack[-1]#當前節點
        if curNode[0]==x2 and curNode[1]==y2:
            #走到終點了
            for p in stack:
                print(p)
            return True
        #(x,y)四個方向:上:(x-1,y),下:(x+1,y),左:(x,y-1),右:(x,y+1)
        for dir in dirs:
            nextNode=dir(curNode[0],curNode[1])
            #如果下一個節點能走
            if maze[nextNode[0]][nextNode[1]]==0:
                stack.append(nextNode)
                maze[nextNode[0]][nextNode[1]]=2#2表示該位置已經走過
                break#能找到一個就break
        else:#如果沒有找到出棧再找
                maze[nextNode[0]][nextNode[1]]=2
                stack.pop()
    else:
        print("沒有路")
        return False
maze_path(1,1,8,8)

問題:路徑不一定是最短的
隊列——廣度優先搜索
思路:從一個節點開始,尋找所有接下來能繼續走的點,繼續不斷尋找,知道找到出口。使用隊列存儲當前正在考慮的節點

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-1,y),
      lambda x,y:(x,y-1),
      lambda x,y:(x,y+1)
      ]
def print_r(path):
    real_path=[]
    i=len(path)-1
    while i>=0:
        real_path.append(path[i][0:2])
        i=path[i][2]
    real_path.reverse()
    for node in real_path:
        print(node)
        
def maze_path_queue(x1,y1,x2,y2):
    #定義一個隊列
    queue=deque()
    path=[]
    queue.append((x1,y1,-1))#起點進隊,-1表示吧位置x1,y1帶進來的節點的位置
    while len(queue)>0:#當隊列不空時循環
        cur_node=queue.popleft()
        path.append(cur_node)
        if cur_node[0]==x2 and cur_node[1]==y2:
            #到達終點
            print(path)
            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))#len(path)-1表示cur_node的位置
                maze[next_node[0]][next_node[1]]=2#走過以後標記爲2
    return False
 
maze_path_queue(1,1,8,8)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章