1.思路:可以敏銳的察覺,迷宮這個問題可以採用遞歸的思路
- 查詢當前位置是否是出口
- 是:返回True
- 否:繼續查找本位置的四個鄰邊位置
- 用for 循環 每一個鄰邊位置都要找
- if 一旦有找到,立即停止搜尋。返回True
- 在程序最後還沒有返回True
- 只好返回 Flase
從這個遞歸過程,讓我再一次深刻認識到遞歸的實現過程:
- 從最簡單的情況開始,返回結果
- 如果沒有到達,最簡單的情況,找到本次情況的下一個情況(有時,不止下一個情況,可能是很多情況並列,比如本題:這個時候就要用if 語句(排除已經訪問過的),或者for 循環來一個一個情況執行),在每一個情況內部:調用函數自己
2.基於遞歸的求解代碼:
# 1.表示迷宮 maze抽象化形成矩陣
#2.利用好遞歸性質
maze=[[0,0,1,1,1],[1,0,1,0,0],[0,0,1,0,0],[1,0,0,1,0],[0,0,0,0,0],[0,1,1,0,1]]
def mark(maze,pos):
maze[pos[0]][pos[1]]=2
def findit(maze,start,end):
dir1=((-1,0),(0,1),(1,0),(0,-1))
#print("調用了幾次find每次的起點是:",start)
if start==end:
print(start) # 注意這裏是無法返回值的
else:
mark(maze,start)
start1=start[:] # 這裏最容易寫成 star1=start
#print("出現一次")
for i in range(0,4):
# print("四個方向 ",start1)
start[0]=start1[0] # 用於保留本次循環起點
start[1]=start1[1]
(start[0],start[1])=(start[0]+dir1[i][0],start[1]+dir1[i][1])
#print("最後",start)
if 0<=start[0]<=len(maze)-1 and 0<=start[1]<=len(maze[0])-1:
if maze[start[0]][start[1]]==0:
findit(maze,start,end)
findit(maze,[1,3],[5,3])
3. 基於堆棧的非遞歸深度優先方法
#利用棧的回溯法,(遞歸的人工實現)
maze=[[0,0,1,1,1],[1,0,1,0,0],[0,0,1,0,0],[1,0,0,1,0],[0,0,0,0,0],[0,1,1,0,1]]
def mark(maze,pos):
maze[pos[0]][pos[1]]=2
def findit(maze,pos,end): # 參數 迷宮矩陣 運動點 終點
dir1=((-1,0),(0,1),(1,0),(0,-1)) # 嚇一跳參數
st= []
if pos==end:
return pos
else:
mark(maze,pos)
st.append(pos)
while st: # 總體就是 先畫出操作圖,在根據圖來把控程序
pos=st.pop()
pos1=pos[:] # 這個細節要注意
for i in range(4):
pos=pos1[:] # 要注意
pos[0],pos[1]=pos[0]+dir1[i][0],pos[1]+dir1[i][1]
#print("四個方向",pos)
if 0<=pos[0]<=len(maze)-1 and 0<=pos[1]<=len(maze[0])-1:
if maze[pos[0]][pos[1]]==0:
if pos==end:
return end
else:
mark(maze,pos)
print("1,4",pos)
st.append(pos)
print("沒有找到")
findit(maze,[1,4],[1,3])
4. 基於隊列的廣度優先算法實現
# 基於隊列的廣度優先
from queue import Queue # 注意命名模塊時不要用預留字
maze=[[0,0,1,1,1],[1,0,1,0,0],[0,0,1,0,0],[1,0,0,1,0],[0,0,0,0,0],[0,1,1,0,1]]
def mark(maze,pos):
maze[pos[0]][pos[1]]=2
def findit(maze,pos,end):
que=Queue()
dir1=((-1,0),(0,1),(1,0),(0,-1)) # 嚇一跳參數
if pos==end:
return pos
else:
que.put(pos)
while not que.empty():
pos1=que.get()
#print(pos1)
mark(maze,pos1)
for i in range(4):
pos=pos1[:]
pos[0],pos[1]=pos[0]+dir1[i][0],pos[1]+dir1[i][1]
if 0<=pos[0]<=len(maze)-1 and 0<=pos[1]<=len(maze[0])-1:
if maze[pos[0]][pos[1]]==0:
if pos==end:
return pos
else:
que.put(pos)
print("沒有找到")
ans=findit(maze,[1,3],[0,1])
print(ans)