揹包問題之動態規劃(Dynamic Programming)問題Python實現

動態規劃問題

動態規劃問題,想法其實很簡單,就是根據貝爾曼最優性原理來求解。
如下圖:
在這裏插入圖片描述
簡單理解:假設圖中ABⅡC是最優的軌跡,那麼,BⅡC一定是最優的軌跡。這一點應該很容易理解。
證明:假設BⅠC比BⅡC更優,那麼AC的最優軌跡就應該爲ABⅠC。矛盾。

揹包問題

考慮一個場景:當你有去沙漠旅行,你有一個揹包和一些物品,揹包有最大承受重量,物品也有重量和價值,而物品種類很多,不可能全都裝在揹包裏,如何去選取價值總量最高的物品組合呢?

物品價值表

物品名 價值
water 10
book 3
food 9
jacket 5
camera 6

物品重量表

物品名 重量
water 3kg
book 1kg
food 2kg
jacket 2kg
camera 1kg

考慮使用貪婪算法,那就是什麼價值高就優先拿什麼,但有時這種近似解會不準,這時就要採用動態規劃方法:從小問題入手,逐步解決大問題,可以幫助你在給定約束條件下找到最優解

思路

對揹包容量,從裝滿到全空,進行迭代。每次都將剩餘的空間裝入價值最大的物品。迭代完成後,即得到最優解。
僞代碼如下:

for 當前剩餘質量 in range(1, 揹包最大質量)for 小於當前剩餘質量的最優解:
		for 物品 in 物品列表:
			if 物品沒有被小於當前剩餘質量的最優解選中 and 物品質量 小於等於 (當前剩餘質量 - 小於當剩餘質量的最優解所使用的質量):
				將該物品放入揹包,並且統計揹包的總價值
		遍歷了物品列表,選出加入了一件新物品後的最優解,即價值最大的
	遍歷所有小於當前剩餘質量最優解後,在上一步價值最大的中選擇價值最大的,成爲新一步的最優解。

talk is cheap, show me the code

#########################################################################
#                      Dynamic Programming
#                           求解揹包問題
#########################################################################

# 物品信息,包含物品質量mass和物品價值value
goods = {
    "water": { "mass": 3, "value": 10 },
    "book": { "mass": 1, "value": 3 },
    "food": { "mass": 2, "value": 9 },
    "jacket": { "mass": 2, "value": 5 },
    "camera": { "mass": 1, "value": 6 }
}

# 揹包容量
package_size = 6

"""
動態規劃問題,根據貝爾曼最優性原理,考慮揹包剩餘容量,保證揹包剩餘容量裝的物品價值最大。
當揹包剩餘容量從0開始循環到揹包最大容量時,即最優解。
"""

# 揹包中各種剩餘容量的最優解, ["camera", "food", "book", 18],最後一個值表示總價值
optimal_answers = []
optimal_answers.append([0])   # 將剩餘容量爲0時最優解加入最優解列表

for remaining_size in range(1, package_size+1):
    temps = []
    for i in range(len(optimal_answers)):    
    # 此處i可以改進,不用每次都從0開始,可以以滿足沒有裝入揹包得物品得最大質量 等於 remaining_size - i爲條件
        # 對相同的remaining_size - i,選取最優的
        temp = []
        for good in goods:
            # 如果該商品沒有放入包裏,且商品的質量小於等於remaining_size - i,則將其放入揹包內
            # print(good, ":", goods[good])
            if not (good in optimal_answers[i]) and (remaining_size - i) >= goods[good]["mass"]:
                opt_ans = optimal_answers[i][:]
                # print(optimal_answers[i])
                # print("opt_ans-optimal_answer:", opt_ans)
                opt_ans.insert(-1, good)
                opt_ans[-1] += goods[good]["value"]
                # print("opt_ans:", opt_ans)
                temp.append(opt_ans)
        
        # print("temp:", temp)
        max_value = 0
        optimal_item = None
        for item in temp:
            # print("item:", item)
            if item[-1] > max_value:
                max_value = item[-1]
                optimal_item = item
        if optimal_item != None:
            temps.append(optimal_item)

    max_values = 0
    optimal_items = None
    # print("temps:", temps)
    for item in temps:
        # print("items:", item)
        if item[-1] > max_values:
            max_values = item[-1]
            optimal_items = item

    optimal_answers.append(optimal_items)
    # print("optimal_answers:", optimal_answers)


print("揹包問題最優解爲:\n揹包的裝法:", optimal_answers[-1][:-1], "\n揹包的總價值爲:", optimal_answers[-1][-1])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章