动态规划问题
动态规划问题,想法其实很简单,就是根据贝尔曼最优性原理来求解。
如下图:
简单理解:假设图中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])