重拾C++之菜鸟刷算法第16篇 --- 动态规划(总结篇)

本文详细介绍了动态规划在01背包问题、完全背包问题以及相关LeetCode题目(如416分割等和子集、1049最后一块石头的重量II等)中的应用,包括dp数组的确定、递推公式、初始化和遍历顺序的讲解。
摘要由CSDN通过智能技术生成

动态规划

五部曲

  1. 确定dp数组的含义
  2. 递推公式
  3. 正确进行初始化
  4. 遍历顺序
  5. 举例推到dp数组

01 背包问题

第一种:填满背包所需的最大价值

有n件物品和一个最多可以背重量为w的背包。第i件物品的重量是weight[i],得到的价值是value[i],所有物品只能使用一次。

滚动数组解法

  1. 首先确定dp数组含义:dp[j] 表示 容量为 j 的背包能背的最大价值是 dp[j]

  2. 确定递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i])

    只有两种情况

    • 第一种是当物品i的重量大于背包j的重量,物品i无法放入背包,因此背包的价值依然和前面相同
    • 第二种是因为dp[j - weight[i]]表示 j - weight[i] 重量的时候,此时最大的价值,那么dp[j - weight[i]] + value[i] 表示此时的背包放入物品i得到的最大价值
  3. 初始化:背包容量为0的话,其价值也为0,因此dp[i] = 0

  4. 遍历顺序:先遍历物品数量,再从背包容量倒序遍历,防止物品重复使用

  5. 举例说明dp数组

416. 分割等和子集 - 力扣(LeetCode)

1049. 最后一块石头的重量 II - 力扣(LeetCode)

第二种:装满容量为x的背包,有几种方法

  1. 首先确定dp数组含义:dp[j] 表示 容量为 j 的背包有 dp[j] 种方法

  2. 确定递推公式:dp[j] += dp[j - weight[i]] (组合类问题)

  3. 初始化:背包容量为0的话,其价值也为0,因此dp[i] = 0

  4. 遍历顺序:先遍历物品数量,再从背包容量倒序遍历,防止物品重复使用

  5. 举例说明dp数组

494. 目标和 - 力扣(LeetCode)

474. 一和零 - 力扣(LeetCode)

完全背包

与01背包唯一不同的地方是,每种物品有无限件

  1. 首先确定dp数组含义:dp[j] 表示 容量为 j 的背包能背的最大价值是 dp[j]

  2. 确定递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i])

    只有两种情况

    • 第一种是当物品i的重量大于背包j的重量,物品i无法放入背包,因此背包的价值依然和前面相同
    • 第二种是因为dp[j - weight[i]]表示 j - weight[i] 重量的时候,此时最大的价值,那么dp[j - weight[i]] + value[i] 表示此时的背包放入物品i得到的最大价值
  3. 初始化:背包容量为0的话,其价值也为0,因此dp[i] = 0

  4. 遍历顺序:先遍历物品数量,再从小到大遍历背包容量(i那位完全背包的物品是可以添加多次的)

  5. 举例说明dp数组

518. 零钱兑换 II - 力扣(LeetCode)

377. 组合总和 Ⅳ - 力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值