經典算法之過河問題python3實現

問題描述

農夫(Human)過河。一個農夫帶着一隻狼(Wolf),一隻羊(Sheep)和一些菜(Vegetable)過河。河邊只有一條船,由於船太小,只能裝下農夫和他的一樣東西。在無人看管的情況下,狼要吃羊,羊要吃菜,請問農夫如何才能使三樣東西平安過河?

要求:
輸出一行,爲最終的過河方式,方案格式爲 過河人員、回來人員、過河人員、回來人員、…、過河人員。
過去和回來的人員之間,用空格隔開。
以四個生物英文的首字母代指對應的生物(H->Human,W->Wolf,S->Sheep,V->Vegetable)

最終輸出示例:HS H HW H

算法實現

使用python舉例

#!/usr/bin/env python3

# H->Human,W->Wolf,S->Sheep,V->Vegetable
name = ["H", "W", "S", "V"]
search_finish = False; # 用於判定 遞歸截止

# 完成狀態的判斷
def is_done(status):
    return status[0] and status[1] and status[2] and status[3]

# 生成下一個局面的所有情況
def generate_next_status(status):
    next_status_list = []

    for i in range(0, 4):
        if status[0] != status[i]: # 和農夫不在一側?
            continue

        next_status = [status[0],status[1],status[2],status[3]]
        # 農夫和其中一個過河,i 爲 0 時候,農夫自己過河。
        next_status[0] = not next_status[0] # 農夫自身取反
        next_status[i] = next_status[0] # 和農夫一起過河
        # 如果是安全的狀態, 那麼將本次狀態加入狀態列表
        if is_valid_status(next_status):
            next_status_list.append(next_status)

    return next_status_list

# 判斷是否合法的局面 安全局面
def is_valid_status(status):
    if status[1] == status[2]:
        if status[0] != status[1]:
            # 狼和羊同側,沒有人在場 不安全
            return False

    if status[2] == status[3]:
        if status[0] != status[2]:
            # 羊和草同側,沒有人在場 不安全
            return False
    return True

# 搜索程序
def do_search(history_status):
    global search_finish

    if search_finish:
        return

    current_status = history_status[len(history_status) - 1] # 獲取當前狀態

    next_status_list = generate_next_status(current_status) # 生成下一次狀態
    for next_status in next_status_list:
        # 去重處理
        if next_status in history_status:
            continue
            
        history_status.append(next_status) # 加入下一個狀態
        # 完成後輸出
        if is_done(next_status):
            search_finish = True
            print(get_solution(history_status))
        else:
            do_search(history_status) # 未完成則繼續搜索

        history_status.pop()

#根據前後狀態輸出過河指標 過去的狀態和現在的狀態對比
def output_cross(pre, now):
    res = [] # 用於存放當前數據
    for i in range(len(pre)):
        if pre[i] != now[i]:
            res.append(name[i])
    return ''.join(res)

#打印過程 根據歷史棧 轉換成 過河標識
def get_solution(history_status):
    result = ''
    hs_len = len(history_status)
    for i in range(hs_len):
        # output_cross
        # 從第二個開始 比較
        if i > 0:
            result += output_cross(history_status[i-1], history_status[i])
            # 不是最後一個
            if i != hs_len - 1:
                result += ' '
    return result

if __name__ == "__main__":
    # 初始化第一次狀態
    status = [False, False, False, False]
    # 初始化歷史狀態
    history_status = [status]
    # 觸發搜索
    do_search(history_status)

最終輸出:
S H HW HS HV H HS

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章