国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python基于回溯法子集樹模板解決野人與傳教士問題示例

2020-01-04 16:43:35
字體:
來源:轉載
供稿:網友

本文實例講述了Python基于回溯法子集樹模板解決野人與傳教士問題。分享給大家供大家參考,具體如下:

問題

在河的左岸有N個傳教士、N個野人和一條船,傳教士們想用這條船把所有人都運過河去,但有以下條件限制:

(1)修道士和野人都會劃船,但船每次最多只能運M個人;
(2)在任何岸邊以及船上,野人數目都不能超過修道士,否則修道士會被野人吃掉。

假定野人會服從任何一種過河安排,請規劃出一個確保修道士安全過河的計劃。

分析

百度一下,網上全是用左岸的傳教士和野人人數以及船的位置這樣一個三元組作為狀態,進行考慮,千篇一律。

我換了一種考慮,只考慮船的狀態。

船的狀態:(x, y) x表示船上x個傳教士,y表示船上y個野人,其中 |x|∈[0, m], |y|∈[0, m], 0<|x|+|y|<=m, x*y>=0, |x|>=|y|

船從左到右時,x,y取非負數。船從右到左時,x,y取非正數

解的編碼:[(x0,y0), (x1,y1), ..., (xp,yp)] 其中x0+x1+...+xp=N, y0+y1+...+yp=N

解的長度不固定,但一定為奇數

開始時左岸(N, N), 右岸(0, 0)。最終時左岸(0, 0), 右岸(N, N)

由于船的合法狀態是動態的、二維的。因此,使用一個函數get_states()來專門生成其狀態空間,使得主程序更加清晰。

代碼

n = 3 # n個傳教士、n個野人m = 2 # 船能載m人x = [] # 一個解,就是船的一系列狀態X = [] # 一組解is_found = False # 全局終止標志# 計算船的合法狀態空間(二維)def get_states(k): # 船準備跑第k趟  global n, m, x  if k%2==0: # 從左到右,只考慮原左岸人數    s1, s2 = n - sum(s[0] for s in x), n - sum(s[1] for s in x)  else:    # 從右到左,只考慮原右岸人數(將船的歷史狀態累加可得?。。。?   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]  # 生成船的合法狀態# 沖突檢測def conflict(k): # 船開始跑第k趟  global n, m, x  # 若船上載的人與上一趟一樣(會陷入死循環?。。。。? if k > 0 and x[-1][0] == -x[-2][0] and x[-1][1] == -x[-2][1]:    return True  # 任何時候,船上傳教士人數少于野人,或者無人,或者超載(計算船的合法狀態空間時已經考慮到了。)  #if 0 < abs(x[-1][0]) < abs(x[-1][1]) or x[-1] == (0, 0) or abs(sum(x[-1])) > m:  #  return True  # 任何時候,左岸傳教士人數少于野人  if 0 < n - sum(s[0] for s in x) < n - sum(s[1] for s in x):    return True  # 任何時候,右岸傳教士人數少于野人  if 0 < sum(s[0] for s in x) < sum(s[1] for s in x):    return True  return False # 無沖突# 回溯法def backtrack(k): # 船準備跑第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: # 左岸人數全為0    print(x)    is_found = True  else:    for state in get_states(k): # 遍歷船的合法狀態空間      x.append(state)      if not conflict(k):        backtrack(k+1) # 深度優先      x.pop()  # 回溯# 測試backtrack(0)

效果圖

Python,回溯法,子集樹模板,野人與傳教士問題

解的解釋,從上往下看:

Python,回溯法,子集樹模板,野人與傳教士問題

一個結論

貌似只有滿足m = n-1,此問題才有解

希望本文所述對大家Python程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 五大连池市| 汉沽区| 呼和浩特市| 如皋市| 泸溪县| 天柱县| 平潭县| 周至县| 桦川县| 县级市| 梧州市| 马山县| 双峰县| 兰州市| 开阳县| 永昌县| 渝北区| 循化| 依兰县| 黎城县| 雷山县| 龙里县| 永平县| 锡林郭勒盟| 达日县| 右玉县| 大港区| 鄯善县| 称多县| 陇西县| 元氏县| 华蓥市| 莒南县| 云浮市| 昌都县| 吉木乃县| 二连浩特市| 冕宁县| 普洱| 汉阴县| 开化县|