我是这样理解动态规划中的背包问题的~

94 阅读1分钟

本文章为看完代码随想录背包问题基础篇后,对背包问题的一些理解

问题描述:

数据:

二维数组:

dp[i][j]含义:从下表为0-i的物品中任意取,放进容量为j的背包,价值总和最大是多少

图片.png

因此只需要判断这两种哪种价值大即可:

第一种写成公式是: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];
}