一、背包问题
1、问题描述
2、引进动态规划表格来解释问题
这个表格中
背包容量:最大值是输入给定,
物品编号:0、表示前0个物品最佳组合;
1、表示前1个物品最佳组合;(所以这里是不是要求物品编号有一定的顺序??)
2、表示前2个物品最佳组合;
空白格子:最佳组合所能产生的价值
3、往动态规划表中填入价值数据
a、物品编号为0,前0物品组合(没有物品),不管背包容量多大,价值为0。
b、背包容量为0,没有物品可以装得下,价值为0
c、背包容量为1,物品编号为1:
(1)如果装1号物品,价值改变;
(2)如果不装1号物品,价值和前0号物品价值想同;
由于装不下1号物品,所有只能选择(2)
d、背包容量为2,物品编号为1:
(1)判断当前背包容量能否装下当前的物品; 能
(2)如果能:判断装下该物品后总价值 和 不装该物品的总价值 那个更大
如果不能:不装该物品,总价值和前一行的总价值相等
d、背包容量为3,物品编号为2:(1)判断当前背包容量能否装下当前的物品; 能
(2)如果能:判断装下该物品后总价值 (4) 和 不装该物品的总价值 (3) 哪个更大
如果不能:不装该物品,总价值和前一行的总价值相等
最后,取总价值大的 4
e、其他空白依次类推,不做详述。。。。
代码实现:
1、数据输入:
n = int(input()) w = list(map(int,input().split())) v = list(map(int,input().split())) c = int(input()) """ 测试数据: n = 4 物品的数量, w = [2, 3, 4, 5] 每个物品的重量, v = [3,4, 5, 6 ] 每个物品的价值, c = 8 书包能承受的重量, """
2、动态规划表的绘制
value = [[0 for j in range(c + 1)] for i in range(n + 1)] #构造一个dp表 for i in range(1, n + 1): for j in range(1, c + 1): if (w[i-1]>j): #如果当前物品质量大于当前背包容量 value[i][j] = value[i-1][j] #不装改物品,总价值和前一个总价值相等 else: #如果可以装下该物品,比较 不装该物品的价值 和 装下该物品后的价值那个更大,取大值。 value[i][j] = max(value[i-1][j],value[i-1][j-w[i-1]]+v[i-1]) for x in value: print(x)
4、背包问题回溯
理解:根据动态规划表的构建,如果当前物品被放入背包中,则当前总价值大于前一行的总价值。
所以可以根据两行总价值 来判断 当前物品是否在背包中。
代码实现:
print('最大价值为:', value[n][c]) x = [False for i in range(n)] j = c for i in range(n, 0, -1): if value[i][j] > value[i - 1][j]: #判断当前价值与前一行的价值 x[i - 1] = True #当前物品置一 j -= w[i - 1] #背包容量里面减去相应的物品容量 print('背包中所装物品为:') for i in range(n): if x[i]: print('第', i+1, '个,', end='')