给定n种物品:
物品i的重量是wi,其价值为vi。
和一个背包:
背包的容量为C。
在选择装入背包的物品时,对于每种物品i只有两种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。
首先:带备忘录的递归方法:
我们利用F(n, C)表示将前n个物品放入容量为C的背包里,得到的最大价值。
推导:使用自顶向下的思想,假如我们已经进行到最后一步(即求解将第n个物品放到背包里获得的最大价值),
此时我们有两种选择:
1.不放第n个物品:此时总价值为F(n - 1, C)
2.放置第n个物品:此时总价值为vn + F(n, c - wn)
/*
根据递归公式F(i, c) = max{F(i - 1, c), vi + F(i, c - wi)}
其中i为第i个物品,c为背包重量,vi为第i个物品的价值,wi为第i个物品的重量
Args:
w 物品的重量数组
v 物品的价值数组
index 当前带选择的物品的索引
capacity 当前背包有效容量
return:
最大价值
*/
上述方法实现了带备忘录的递归方法,即不用多次求解子问题。
动态规划方法 规划的条件依然是物品的下标i和背包的容量capacity:
动态规划算法通过状态转移方程直接构建dp数组
其中第一行要先确定,即将第一个物品在容量分别为0-capacity时存入数组,随后根据上一个物品决定新的物品是否放入背包。
上述代码也可以从1开始保存。即id为0时认为没有物品。
即将备忘录改为:
同时初始化代码改为:
代码可进行优化,因为我们发现dp[i][j]中的i只与上一行有关,所以我们可以把二维数组变为一位数组,只存上一行保存的数据。