動態規劃問題
動態規劃問題,想法其實很簡單,就是根據貝爾曼最優性原理來求解。
如下圖:
簡單理解:假設圖中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])