本文章为看完代码随想录背包问题基础篇后,对背包问题的一些理解
问题描述:
数据:
二维数组:
dp[i][j]含义:从下表为0-i的物品中任意取,放进容量为j的背包,价值总和最大是多少
因此只需要判断这两种哪种价值大即可:
第一种写成公式是:dp[i-1][j]
第二种写成公式是: dp[i-1][j-weight[i]]+value[i]
由此递推公式为:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
function knaspsackProblem_method1(weight,value,size){
const len=weight.length,
// 初始化dp数组
dp=Array(len).fill().map(()=>Array(size+1).fill(0));
for(let i=weight[0];i<=size;i++){
dp[0][i]=value[0];
}
for(let i=1;i<len;i++){ //遍历物品
for(let j=0;j<=size;j++){ //遍历背包容量
if(j<weight[i]) dp[i][j]=dp[i-1][j];
else dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
}
}
return dp[len-1][size];
}
一维数组
dp数组:容量为j的背包,所背的物品最大价值为dp[j]
递推公式:dp[j]=Math.max(dp[j],dp[j-weight[i]]+value[i]);
理解:1.一维数组是二维数组的简化版
2.通过for循环的方式,遍历不同物品和不同容积的背包进行dp数组的赋值
注意点:1.二维数组种dp数组循环赋值没有嵌套顺序,而一维数组必须是先循环商品,再循环背包
2.遍历背包时必须倒着遍历,否则会出现重复取值情况
function knaspsackProblem_method2(weight,value,size){
// 初始化
const len=weight.length,
dp=Array(size+1).fill(0)
for(let i=1;i<len;i++){
for(let j=size;j>=weight[i-1];j--){
dp[j]=Math.max(dp[j],dp[j-weight[i]]+value[i]);
}
}
return dp[size];
}