一,问题
【问题】
一个容量为m公斤的背包。现有n种物品,每种物品有无限多件,它们的重量分别为W[i](1<=
i<=n),它们的价值分别为C[i](1<=i<=n)。求能放入背包的最大价值。
【输入】
第一行:两个整数,n(物品数量,n<51)和m(背包容量,m<201)。
第2,3.......n+1行:每行两个整数W[i],C[i],表示每个物品的重量和价值。
【输出】
一个数,表示最大价值。
【样例输入】
3 6
2 3
4 7
3 6
【样例输出】
12
二,解答思路
动态规划的一般步骤:
1.确定状态变量(函数);
2.确定转移方程(递推关系);
3.确定边界条件;
4.确定递推顺序。
最大价值是物品数量 i 和背包容量 j 的函数。
设函数 f[i][j] 表示前 i 件物品放入容量为 j 的背包的最大价值。
最终的最大价值就是物品数量 i 从0增长到 n,背包容量 j 从0增长到 m 时的 f[n][m]值。
若当前背包容量为 j ,那我们就要考虑第 i 件物品能否放入或是否放入?
1,当前背包容量 j<W[i], 不能放入,则 f[ i [ j ]=f[ i-1 ][ j ];
2,当前背包容量 j>=W[i],能放入,但要比较价值:
(1)若第 i 件物品不放入背包,则 f[ i ][ j ]=f[i-1][ j ];
(2)若第 i 件物品放入背包,则f[ i ][ j ]=f[ i ][ j-W[ i ] ]+C[ i ]
对于前 i 件物品,背包容量为 j-W[i] 时可能已经放入了第 i 件物品,容量为 j 时还可以放入第 i 件物品,所以用 f[ i ][ j-W[i] ]更新 f[ i ][ j ]。
为方便理解,举个例子:
三 ,代码
我们还可以做进一步的优化:
用一维数组 f[ j ] 只记录一行数据。让 j 值顺序循环,顺序更新 f[ j ] 的值。
为什么呢?因为 j 是顺序循环,f[ j-w[i] ]会先于 f[ j ] 更新,也就是说,用 新值 f[ j-w[i] ] 去更新 f[ j ],相当于用第 i 行的 f[ j-w[i] ] 的值更新 f[ j ],所以可以。
相比有人已经意识到了,还可以做进一步地简化: