Python基于回溯法子集樹(shù)模板解決野人與傳教士問(wèn)題示例
本文實(shí)例講述了Python基于回溯法子集樹(shù)模板解決野人與傳教士問(wèn)題。分享給大家供大家參考,具體如下:
問(wèn)題
在河的左岸有N個(gè)傳教士、N個(gè)野人和一條船,傳教士們想用這條船把所有人都運(yùn)過(guò)河去,但有以下條件限制:
(1)修道士和野人都會(huì)劃船,但船每次最多只能運(yùn)M個(gè)人;
(2)在任何岸邊以及船上,野人數(shù)目都不能超過(guò)修道士,否則修道士會(huì)被野人吃掉。
假定野人會(huì)服從任何一種過(guò)河安排,請(qǐng)規(guī)劃出一個(gè)確保修道士安全過(guò)河的計(jì)劃。
分析
百度一下,網(wǎng)上全是用左岸的傳教士和野人人數(shù)以及船的位置這樣一個(gè)三元組作為狀態(tài),進(jìn)行考慮,千篇一律。
我換了一種考慮,只考慮船的狀態(tài)。
船的狀態(tài):(x, y) x表示船上x(chóng)個(gè)傳教士,y表示船上y個(gè)野人,其中 |x|∈[0, m], |y|∈[0, m], 0<|x|+|y|<=m, x*y>=0, |x|>=|y|
船從左到右時(shí),x,y取非負(fù)數(shù)。船從右到左時(shí),x,y取非正數(shù)
解的編碼:[(x0,y0), (x1,y1), ..., (xp,yp)] 其中x0+x1+...+xp=N, y0+y1+...+yp=N
解的長(zhǎng)度不固定,但一定為奇數(shù)
開(kāi)始時(shí)左岸(N, N), 右岸(0, 0)。最終時(shí)左岸(0, 0), 右岸(N, N)
由于船的合法狀態(tài)是動(dòng)態(tài)的、二維的。因此,使用一個(gè)函數(shù)get_states()來(lái)專門(mén)生成其狀態(tài)空間,使得主程序更加清晰。
代碼
n = 3 # n個(gè)傳教士、n個(gè)野人
m = 2 # 船能載m人
x = [] # 一個(gè)解,就是船的一系列狀態(tài)
X = [] # 一組解
is_found = False # 全局終止標(biāo)志
# 計(jì)算船的合法狀態(tài)空間(二維)
def get_states(k): # 船準(zhǔn)備跑第k趟
global n, m, x
if k%2==0: # 從左到右,只考慮原左岸人數(shù)
s1, s2 = n - sum(s[0] for s in x), n - sum(s[1] for s in x)
else: # 從右到左,只考慮原右岸人數(shù)(將船的歷史狀態(tài)累加可得!?。。?
s1, s2 = sum(s[0] for s in x), sum(s[1] for s in x)
for i in range(s1 + 1):
for j in range(s2 + 1):
if 0 < i+j <= m and (i*j == 0 or i >= j):
yield [(-i,-j), (i,j)][k%2==0] # 生成船的合法狀態(tài)
# 沖突檢測(cè)
def conflict(k): # 船開(kāi)始跑第k趟
global n, m, x
# 若船上載的人與上一趟一樣(會(huì)陷入死循環(huán)!?。。。?
if k > 0 and x[-1][0] == -x[-2][0] and x[-1][1] == -x[-2][1]:
return True
# 任何時(shí)候,船上傳教士人數(shù)少于野人,或者無(wú)人,或者超載(計(jì)算船的合法狀態(tài)空間時(shí)已經(jīng)考慮到了。)
#if 0 < abs(x[-1][0]) < abs(x[-1][1]) or x[-1] == (0, 0) or abs(sum(x[-1])) > m:
# return True
# 任何時(shí)候,左岸傳教士人數(shù)少于野人
if 0 < n - sum(s[0] for s in x) < n - sum(s[1] for s in x):
return True
# 任何時(shí)候,右岸傳教士人數(shù)少于野人
if 0 < sum(s[0] for s in x) < sum(s[1] for s in x):
return True
return False # 無(wú)沖突
# 回溯法
def backtrack(k): # 船準(zhǔn)備跑第k趟
global n, m, x, is_found
if is_found: return # 終止所有遞歸
if n - sum(s[0] for s in x) == 0 and n - sum(s[1] for s in x) == 0: # 左岸人數(shù)全為0
print(x)
is_found = True
else:
for state in get_states(k): # 遍歷船的合法狀態(tài)空間
x.append(state)
if not conflict(k):
backtrack(k+1) # 深度優(yōu)先
x.pop() # 回溯
# 測(cè)試
backtrack(0)
效果圖

解的解釋,從上往下看:

一個(gè)結(jié)論
貌似只有滿足m = n-1,此問(wèn)題才有解。
更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python Socket編程技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門(mén)與進(jìn)階經(jīng)典教程》及《Python文件與目錄操作技巧匯總》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
Python Django框架實(shí)現(xiàn)應(yīng)用添加logging日志操作示例
這篇文章主要介紹了Python Django框架實(shí)現(xiàn)應(yīng)用添加logging日志操作,結(jié)合實(shí)例形式分析了Django框架中添加Python內(nèi)建日志模塊相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
利用Python實(shí)現(xiàn)生成顏色表(color chart)
在做色彩相關(guān)的算法分析時(shí)候,經(jīng)常需要使用規(guī)則的顏色表來(lái)進(jìn)行輔助,本文就來(lái)利用numpy和opencv生成顏色表并保存為圖片,需要的可以參考一下2023-05-05
pytorch?rpc實(shí)現(xiàn)分物理機(jī)器實(shí)現(xiàn)model?parallel的過(guò)程詳解
這篇文章主要介紹了pytorch?rpc實(shí)現(xiàn)分物理機(jī)器實(shí)現(xiàn)model?parallel的過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
39條Python語(yǔ)句實(shí)現(xiàn)數(shù)字華容道
這篇文章主要為大家詳細(xì)介紹了39條Python語(yǔ)句實(shí)現(xiàn)數(shù)字華容道,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
python包相關(guān)知識(shí)點(diǎn)之包的導(dǎo)入、相對(duì)路徑以及絕對(duì)路徑
Python的好處在于你不需要懂很多概念,你就有機(jī)會(huì)投入工作,同樣問(wèn)題也有機(jī)會(huì)隨時(shí)發(fā)生,下面這篇文章主要給大家介紹了關(guān)于python包相關(guān)知識(shí)點(diǎn)之包的導(dǎo)入、相對(duì)路徑以及絕對(duì)路徑的相關(guān)資料,需要的朋友可以參考下2022-04-04
利用標(biāo)準(zhǔn)庫(kù)fractions模塊讓Python支持分?jǐn)?shù)類(lèi)型的方法詳解
最近在工作中遇到了分?jǐn)?shù)處理,查找相關(guān)的資料發(fā)現(xiàn)可以利用Fraction類(lèi)來(lái)實(shí)現(xiàn),所以下面這篇文章主要給大家介紹了關(guān)于利用標(biāo)準(zhǔn)庫(kù)fractions模塊讓Python支持分?jǐn)?shù)類(lèi)型的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-08-08
淺談django的render函數(shù)的參數(shù)問(wèn)題
今天小編就為大家分享一篇淺談django的render函數(shù)的參數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
Flask框架請(qǐng)求鉤子與request請(qǐng)求對(duì)象用法實(shí)例分析
這篇文章主要介紹了Flask框架請(qǐng)求鉤子與request請(qǐng)求對(duì)象用法,結(jié)合實(shí)例形式詳細(xì)分析了Flask框架請(qǐng)求鉤子與request請(qǐng)求對(duì)象相關(guān)原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2019-11-11

