0-1背包问题——动态规划

问题描述:

给定一些商品,包括商品的价格和体积,选定若干个商品装进固定容量的背包,选定商品的价格总和最大且总容量不超过背包容量。0-1背包问题仅有是否装入两种情况。

蛮力枚举


def KnapsackSR(i, c, vi, pi):
	"""
    :param pi: 商品价格的列表
    :param vi: 商品体积的列表
    :param i: 前i个商品
    :param c: 容量为c时最优解
    :return: 最大总价格
    """
    if c < 0:	# 如果背包容量小于0,返回负无穷
    	return float("-inf")
    if i < 0:	# 如果商品序号小于0,返回0
    	return 0
    # P1为选择某种商品后进行递归求解
    P1 = KnapsackSR(i - 1, c - vi[i], vi, pi)
    # P2为不选择某种商品后进行递归求解
    P2 = KnapsackSR(i - 1, c, vi, pi)
    # 返回P1和P2之间的最大值,即为所求最优解
    P = max(P1 + pi[i], P2)
    return P
    

带备忘递归

  1. 方法一:

def KnapsackMR(i, c, vi, pi):
	"""
    :param i: 商品的序号
    :param c: 背包容量
    :param vi: 商品的体积
    :param pi: 商品的价格
    :return: 装进背包的容量对应的最大价格
    """
    i_list = []
    if c < 0:
    	return float("-inf"), []
    if i < 0:
    	return 0, []
    P1, i_list1 = KnapsackMR(i - 1, c - vi[i], vi, pi)
    P2, i_list2 = KnapsackMR(i - 1, c, vi, pi)
    P = max(P1 + pi[i], P2)
    if P == P1 + pi[i]:
    	i_list.extend(i_list1)
    	i_list.append(i)
    else:
    	i_list.extend(i_list2)
    return P, i_list

  1. 方法二:

def KnapsackMR(i, c, vi, pi):
    """
    :param i: 商品的序号
    :param c: 背包容量
    :param vi: 商品的体积
    :param pi: 商品的价格
    :return: 装进背包的容量对应的最大价格
    """
    # 构造备忘录P[i,c],表示在前i个商品中选择,背包容量为c时的最优解
    P = [[for j in range(c + 1)] for k in range(i + 1)]
    if c < 0:
    	return float("-inf")
    if i < 0:
    	return 0
   	P1 = KnapsackMR(i - 1, c - vi[i], vi, pi)
   	P2 = KnapsackMR(i - 1, c, vi, pi)
   	P[i][c] = max(P1 + pi[i], P2)
   	return P[i][c]

递推计算(动态规划)


import copy


def KnapsackDP(n, p, v, C):
    """
    :param n: 商品数量
    :param p: 各商品的价值
    :param v: 各商品的体积
    :param C: 背包容量
    :return: 商品价格的最大值
    """
    # 初始化,创建二维数组P[0...n,0...C]和REC[0...n,0...C]
    P = [[0 for i in range(C + 1)] for j in range(n + 1)]
    Rec = [[0 for i in range(C + 1)] for j in range(n + 1)]

	# 求解表格,依次计算子问题
	# 因为i是从1开始的,所以进行商品选择和记录时需要在原始基础上减1
    for i in range(1, n + 1):
    	for c in range(1, C + 1):
    		# 选择商品i
    		if v[i - 1] <= c and (p[i - 1]+ P[i - 1][c-v[i - 1]]>P[i - 1][c]):
	    		# 记录价格和决策
	    		P[i][c] = p[i-1]+P[i-1][c-v[i-1]]
	    		Rec[i][c] = 1
	    	# 不选择商品i
    		else:
    			P[i][c] = p[i - 1][c]
    			Rec[i][c] = 0
    # 输出最优解方案
    K = copy.deepcopy(C)
    for i in reversed(range(1, n + 1)):
    	if Rec[i][K] == 1:
    		print("选择商品序号(从1到n):", i)
    		K -= v[i - 1]
    	else:
    		print("不选择商品序号(从1到n):", i)
    return P[n][C]

if __name__ == "__main__":
	v = [10, 3, 4, 5, 4]
	p = [24, 2, 9, 10, 9]
	print("商品价格最大值:", KnapsackDP(len(v), p, v, 13)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值