0-1背包问题
给定背包容量W,一系列物品{weight,value},每个物品只能取一件,求最大价值
采用动态规划解决
(动态规划从前往后,后面的值取决于前面的直接用就可以,像填格子)
找到关键位置
第i个物品,装还是不装
- 装
如果装,则最大价值取决于前i-1个物品在背包重量为W-weight(i)的情况下的值和不装的值的最大值
f[i][j] = Math.max(f[i-1][j],values[i]+f[i-1][j-weights[i]])
- 不装
如果不装,则最大价值取决于前i-1个物品在背包重量为W的情况下的最大值
f[i][j] = f[i-1][j]
完整代码:
function knapsack(weights,values,w) {
//参数含义:weights:物品重量数组,values:物品价值数组,w:总重量
//n:物品总个数
let n = weights.length;
//f为二维数组
let f = [[]];
//只装物品0
for (let i = 0;i<=w;i++) {
//f[0][i]表示只可选的物品为0号物品,背包总承重为i时的最大价值
//如果背包总承重i小于第0个物品的重量,则什么也装不了最大价值就为0
if (i < weights[0]) f[0][i] = 0;
//能装了,最大价值就为0号物品的价值
else f[0][i] = values[0];
}
//填格子,一行一行横着填,只可选i个物品,背包最大承重为j,第i行,第j列
for (let i = 1; i < n; i++) {
for (let j = 0; j<=w; j++) {
//开始只有第一行,再一行一行开拓出来
if (!f[i]) f[i] = [];
//背包装不了第i个,所以最大价值为能选i-1个,背包重量为j的价值
if (j < weights[i]) f[i][j] = f[i-1][j];
//能装了,挑装还是不装的最大价值
else f[i][j] = Math.max(f[i-1][j],values[i]+f[i-1][j-weights[i]]);
}
}
//背包能选n-1个物品,最大承重为w时的最大价值
return f[n-1][w];
};
console.log(knapsack([2,2,6,5,4],[6,3,5,4,6],10));