问题描述
有n个物品,它们有各自的容量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
动态规划解决01背包,最重要的是填表,表会填,就理解
确定递推公式
value[i]:代表第i个物品的价值
weight[i]:代表第i个物品的体积(重量,体积,容量其实说的是一回事)
j表示为此时的背包容量
dp[i] [j]: 0到i之间的物品任取放入容量为j的背包中
那如果是dp[ i-1 ] [ j ]呢?
那就是:
0到i-1之间的物品中任取放入容量为j的背包中
那可以从几个方向可以得到dp[i] [j]呢?
- 不放第i个物品时的最大价值: dp[i-1] [j]
- 放入第i个物品时的最大价值:dp[ i-1 ] [ j-weight [ i]]+value[i]
因为我们求的是最大价值呀,因此取不放第i个物品时的最大价值和放入第i个物品时的最大价值的最大值,虽然说的有点啰嗦,但还是好理解的…
故可以表示为:dp[i] [j]=max{ dp[i-1] [j],dp[i-1] [j-weight[i]]+value[i] }
【注】:
- 放入第i个物品的时候,得先知道不放第i个物品时背包的容量吧。因此可以写一个等式来理解一下:
放入第i个物品时的最大价值=不放第i个物品时的最大价值+第i个物品的价值 - dp[i] [j]是一个二维数组,它的值表示的含义是此时背包可以装入的最大价值
- dp[i-1] [j-weight[i]]:0到i-1的物品之间任取物品,放入容量为没有放入第i个物品的背包中,其中j-weight[i]就表示没有放入第i个物品背包的容量,也就是此时背包容量为j,减去第i个背包的重量。
故当前元素可以有正上方和左上方的元素递推出来。
不放物品i的意思应该是放不了物品i
为什么放不了?因为
j<weight[i],则dp[i] [j]=dp[i-1] [j]
j>=weight[i],则dp[i] [j]=dp[ i-1 ] [ j-weight [ i]]+value[i]
动态规划解决01背包问题的核心思想是:先倒推出一个递推公式,然后顺推出第一步,接下来利用递推公式推演出所有结果和步骤。
因此我们便有了一个思路:一个题目要顺推很多次,不妨倒推一个递推公式,然后顺推第一步。
- 当背包容量大于此时物品重量时,则要考虑回溯并加值即j>weight[i]这种情况;
- 当背包容量小于此时物品重量时,则维持不变
两层for循环,一层背包,一层物品,对于二维的dp数组是可以颠倒的。