給一個二維列表,表示迷宮(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)