最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python基于回溯法子集樹(shù)模板解決野人與傳教士問(wèn)題示例

 更新時(shí)間:2017年09月11日 11:38:47   作者:羅兵  
這篇文章主要介紹了Python基于回溯法子集樹(shù)模板解決野人與傳教士問(wèn)題,簡(jiǎn)單說(shuō)明了野人與傳教士問(wèn)題,并結(jié)合實(shí)例形式分析了Python使用回溯法子集樹(shù)模板解決野人與傳教士問(wèn)題的步驟與相關(guā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)文章

最新評(píng)論

彭阳县| 荆州市| 麦盖提县| 南郑县| 双鸭山市| 甘孜县| 定结县| 安国市| 衢州市| 南开区| 东港市| 昌吉市| 城市| 无棣县| 小金县| 罗城| 博野县| 修文县| 孟津县| 区。| 惠州市| 黎平县| 勃利县| 平果县| 鄂尔多斯市| 通城县| 海阳市| 西华县| 拜泉县| 南开区| 克什克腾旗| 凤山县| 潢川县| 偃师市| 上高县| 英超| 黄冈市| 县级市| 襄垣县| 兴义市| 桐庐县|