傳教士與食人者問題python

專注的阿熊發表於2021-04-23

g = {}  # 存放父子節點

statusl = []# 表示方式 [ML, CL, MR, CR, B]   左傳教士、左野人、右傳教士、右野人、船

route = []  # 一次路徑

way = []  # 總路徑

actions = [[1, 0], [0, 1], [1, 1], [0, 2], [2, 0]]  # 五種操作方式

def result(s):

    if s[0] < 0 or s[1] < 0 or s[2] < 0 or s[3] < 0:  # 負數

        return

    if (s[0] < s[1] and s[0] != 0) or (s[2] < s[3] and s[2] != 0):  # 傳教士被吃

        return

    d = tuple(s)    # 元組作為狀態點

    if len(statusl) > 1:

        f = tuple(statusl[-2][:])

        if f in g.keys() and d not in g[f]:

            g[f].append(d)

        else:

            g[f] = [d]

    for k in statusl[:-1]:   # 重複狀態

        if k[0] == s[0] and k[1] == s[1] and k[3] == s[3] and k[4] == s[4]:

            return

    mid = [0] * 5

    for j in actions:

        mid[0] = s[0] - j[0] * s[4]

        mid[1] = s[1] - j[1] * s[4]

        mid[2] = s[2] + j[0] * s[4]

        mid[3] = s[3] + j[1] * s[4]

        mid[4] = -s[4]

        statusl.append(mid[:])

        result(mid)   # 判斷該動作是否合理,並加入字典

        statusl.pop()

    return

# 深度搜尋尋找路徑

def dfs(s):

    s = tuple(s)     # 字典的值是列表裡面包含元組,原因是字典的鍵值不能是列表

    if s in route:   # 已經在路徑裡面

        route.append(s)

        return

    # 到達終點,記錄路徑

    if s == (0, 0, 3, 3, -1):

        route.append(s)

        way.append(route[:])

        return

    route.append(s)

    for i in range(len(g[s])):

        dfs(g[s][i])   # 遞迴搜尋直到到達終點或者重複

        route.pop()

def main():

    start = [3, 3, 0, 0, 1]

    statusl.append(start)

    result(start)

    dfs(start)

    num = 0   # 統計次數

    # 輸出路徑

    for k in way:

        num += 1

        print(" 外匯跟單gendan5.com %d 條路徑: " % num)

        print(" 左傳教士 , 左食人者 , 右傳教士 , 右食人者 ,   ")

        for i in k:

            print("{}       {}       {}       {}       {}   ".format(i[0], i[1], i[2], i[3], i[4]))

    print(" 總共有 %d 條路徑 " % num)

 

if __name__ == '__main__':

    main()


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2769585/,如需轉載,請註明出處,否則將追究法律責任。

相關文章