背包问题之动态规划(Dynamic Programming)问题Python实现

动态规划问题

动态规划问题,想法其实很简单,就是根据贝尔曼最优性原理来求解。
如下图:
在这里插入图片描述
简单理解:假设图中ABⅡC是最优的轨迹,那么,BⅡC一定是最优的轨迹。这一点应该很容易理解。
证明:假设BⅠC比BⅡC更优,那么AC的最优轨迹就应该为ABⅠC。矛盾。

背包问题

考虑一个场景:当你有去沙漠旅行,你有一个背包和一些物品,背包有最大承受重量,物品也有重量和价值,而物品种类很多,不可能全都装在背包里,如何去选取价值总量最高的物品组合呢?

物品价值表

物品名价值
water10
book3
food9
jacket5
camera6

物品重量表

物品名重量
water3kg
book1kg
food2kg
jacket2kg
camera1kg

考虑使用贪婪算法,那就是什么价值高就优先拿什么,但有时这种近似解会不准,这时就要采用动态规划方法:从小问题入手,逐步解决大问题,可以帮助你在给定约束条件下找到最优解

思路

对背包容量,从装满到全空,进行迭代。每次都将剩余的空间装入价值最大的物品。迭代完成后,即得到最优解。
伪代码如下:

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])
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值