背包问题

87 阅读1分钟

01背包

题目

某个背包拥有最大容量m,有一些物品拥有weight[i], 价值为 value[i], 每个物品只有一个,可以取1个也可以不取,求在不超过最大容量 m 下的最高价值.

解法

  1. 首先心中要有二维数组 dp[i][j]表示以从第0个到第 i个物品取,价值为j,所能获得的最大价值  dp[i][j] = max(dp[i-1][j], dp[j-weight[i]] + values[i]) 通过画图分析可得,第 i 行数据取决于i-1行数据,且右下角取决于左上角,接着可以优化为一维数组
// 逐行遍历物品 j倒序保证第0个物品的状态正确,只放入一次
for (int i = 0; i < weight.length; i++) {
    for (int j = bagWeight; j >= weight[i]; j--) {
        dp[j] = max(dp[j], dp[j - weight[i]] + values[i]);
    }
}

小结:01背包的一维数组要求 j 倒序且只能先遍历物品

完全背包

题目

和01背包的区别就是取的数目可以不限,因此遍历 j 的时候为正序,且先遍历容量还是先遍历物品都可以 题目:零钱兑换(最小硬币数。不需要在意遍历顺序,组合总数,需要在意遍历顺序)

解法

  1. 如果求组合数就是外层for循环遍历物品,内层for遍历背包**。
  2. 如果求排列数就是外层for遍历背包,内层for循环遍历物品**。