問題
給定乙個迷宮,入口已知。問是否有路徑從入口到出口,若有則輸出一條這樣的路徑。注意移動可以從上、下、左、右、上左、上右、下左、下右八個方向進行。迷宮輸入0表示可走,輸入1表示牆。為方便起見,用1將迷宮圍起來避免邊界問題。
分析考慮到左、右是相對的,因此修改為:北、東北、東、東南、南、西南、西、西北八個方向。在任意一格內,有8個方向可以選擇,亦即8種狀態可選。因此從入口格仔開始,每進入一格都要遍歷這8種狀態。
顯然,可以套用回溯法的子集樹模板。
注意,解的長度是不固定的。
**# 迷宮(1是牆,0是通路)
maze = [[1,1,1,1,1,1,1,1,1,1],
[0,0,1,0,1,1,1,1,0,1],
[1,1,0,1,0,1,1,0,1,1],
[1,0,1,1,1,0,0,1,1,1],
[1,1,1,0,0,1,1,0,1,1],
[1,1,0,1,1,1,1,1,0,1],
[1,0,1,0,0,1,1,1,1,0],
[1,1,1,1,1,0,1,1,1,1]]
m, n = 8, 10 # 8行,10列
entry = (1,0) # 迷宮入口
path = [entry] # 乙個解(路徑)
paths = # 一組解
# 移動的方向(順時針8個:n, en, e, es, s, ws, w, wn)
directions = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]
# 衝突檢測
def conflict(nx, ny):
global m,n,maze
# 是否在迷宮中,以及是否可通行
if 0 <= nx < m and 0 <= ny < n and maze[nx][ny]==0:
return false
return true
# 套用子集樹模板
def walk(x, y): # 到達(x,y)格仔
global entry,m,n,maze,path,paths,directions
if (x,y) != entry and (x % (m-1) ==0 or y % (n-1) == 0): # 出口
#print(path)
paths.append(path[:]) # 直接儲存,未做最優化
else:
for d in directions: # 遍歷8個方向(亦即8個狀態)
nx, ny = x+d[0], y+d[1]
path.append((nx,ny)) # 儲存,新座標入棧
if not conflict(nx, ny): # 剪枝
maze[nx][ny] = 2 # 標記,已訪問(奇怪,此兩句只能放在if區塊內!)
walk(nx, ny)
maze[程式設計客棧nx][ny] = 0 # 回溯,恢復
path.pop() # 回溯,出棧
# 解的視覺化(根據乙個解x,復原迷宮路徑,'2'表示通路)
def show(path):
gl程式設計客棧obal maze
import www.cppcns.compprint, copy
maze2 = copy.deepcopy(maze)
for p in path:
maze2[p[0]][p[1]] = 2 # 通路
pprint.pprint(maze) # 原迷宮
print()
pprint.pprint(maze2) # 帶通路的迷宮
# 測試
walk(1,0)
print(paths[-1], '\n') # 看看最後一條路徑
show(paths[-1])
效果圖
Python使用回溯法子集樹模板解決爬樓梯問題示例
問題 某樓梯有n層台階,每步只能走1級台階,或2級台階。從下向上爬樓梯,有多少種爬法?分析這個問題之前用分治法解決過。但是,這裡我要用回溯法www.cppcns.com子集樹模板解決它。祭出元素 狀態空間分析 每一步是乙個元素,可走的步數 1,2 就是其狀態空間。不難看出,元素不固定,狀態空間固定。...
python 用回溯法(子集樹)解n皇后問題
n皇后問題 如何能夠在 n n 的西洋棋棋盤上放置n個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后。為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。def backtrack t,n 核心 if t n output return else for i in range n a t ...
Python 回溯法 子集樹模組系列 八皇后問題
案例 八皇后問題是乙個以西洋棋為背景的問題 如何能夠在 8 8 的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題 這時棋盤的大小變為n n,而皇后個數也變成n。當且僅當 n ...