当前位置: 首页 > news >正文

代码随想录算法训练营第38天—动态规划06 | ● 完全背包 ● *518. 零钱兑换 II ● 377. 组合总和 Ⅳ

完全背包

视频讲解:https://www.bilibili.com/video/BV1uK411o7c9
https://programmercarl.com/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85.html

  • 题目描述:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品可以重复使用,求解怎么装背包里物品价值总和最大。
  • 解法大体和01背包的解法相同,以下以一维数组解法为例,其和01背包的解法主要有两点不同:
    • 一是内层for循环从逆向遍历改为正向遍历,因为完全背包里的每个物品是可以多次放入背包中的
    • 二是对于纯完全背包问题,内外层for循环是可以颠倒的,也就是说先遍历物品和先遍历背包容量都可以,其中为什么先遍历背包容量也可以呢?这样不会导致过程中某些dp[j]依赖于了下一个物品的dp[j]吗?其实是没关系的,无论是否依赖了下一个物品,我们最终得到的最后的那个结果值都不会变,也就是说过程中即便发生了变化,结果仍然是正确的。但从理论上来讲,其实还是应该先遍历物品,这样每一步都是正确的,不会产生困惑
      • 而对于完全背包应用类题目里的求装满背包有多少种情况的问题,内外层循环的顺序有如下讲究
        • 先遍历物品,再遍历背包容量,得到的结果是组合数——因为此时在不同种背包容量的情况里,都是先放进物品1再放进物品2,不会出现先放2再放1的情况,此时得到的组合之间不会出现顺序不同、元素相同的情况
        • 先遍历背包容量,再遍历物品,得到的结果是排列数——因为此时在背包容量递增的过程中,物品1和物品2放入的先后顺序不一定,可能先放了1也可能先放了2,因此集合之间会出现顺序不同、元素相同的情况,也就是得到的结果是排列数
  • 滚动数组(一维数组解法)
    • 动规五部曲
      • 一维dp数组dp[j]
        • 其中j代表背包的容量,dp值代表对应的最大价值
      • 递推公式
        • 当前 j 对应的最大价值为 装第i个物品不装第i个物品 两种情况里的较大值
        • 其中装第i个物品对应的dp值为dp[j - weight[i]] + value[i],weight[i]表示第i个物品的重量,value[i]代表第i个物品的价值
        • 不装第i个物品对应的dp值为dp[j]
        • dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
      • 一维dp数组的初始化
        • 全部初始化为0即可
      • 遍历顺序
        • 对于纯完全背包类问题,内外层for循环可以互相颠倒,但是二者的遍历顺序均是从前往后
      • 无需打印
    • 代码书写问题
# 一维数组解法
# m种物品,背包容量为n,每个物品的重量和价值分别保存在weight和value里
dp = [0] * (n + 1)
for i in range(1, m):for j in range(1, n + 1):if (j - weight[i]) >= 0:dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
print(dp[-1])

*518. 零钱兑换 II

视频讲解:https://www.bilibili.com/video/BV1KM411k75j
https://programmercarl.com/0518.%E9%9B%B6%E9%92%B1%E5%85%91%E6%8D%A2II.html

  • 考点
    • 动态规划
    • 完全背包
    • 组合和排列(下一道题就是排列问题)
  • 我的思路
    • 思路就是给一个背包和给多个物品,问装满背包有多少种组合(每个物品可以重复拿取)
  • 视频讲解关键点总结
    • 我的思路没有问题,需要注意的是,不同的内外循环顺序会带来不同的结果,一种计算的是组合数,一种计算的是排列数(相同的元素,不同的顺序也视为不同)
      • 先遍历物品,再遍历背包容量,得到的结果是组合数——因为此时在不同种背包容量的情况里,都是先放进物品1再放进物品2,不会出现先放2再放1的情况,此时得到的组合之间不会出现顺序不同、元素相同的情况
      • 先遍历背包容量,再遍历物品,得到的结果是排列数——因为此时在背包容量递增的过程中,物品1和物品2放入的先后顺序不一定,可能先放了1也可能先放了2,因此集合之间会出现顺序不同、元素相同的情况,也就是得到的结果是排列数
  • 我的思路的问题
  • 代码书写问题
  • 可执行代码
class Solution:def change(self, amount: int, coins: List[int]) -> int:dp = [0] * (amount + 1)dp[0] = 1for i in range(len(coins)):for j in range(1, amount + 1):if j >= coins[i]:dp[j] += dp[j - coins[i]]return dp[-1]

377. 组合总和 Ⅳ

视频讲解:https://www.bilibili.com/video/BV1V14y1n7B6
https://programmercarl.com/0377.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C%E2%85%A3.html

  • 考点
    • 动态规划
    • 完全背包
    • 组合和排列
  • 我的思路
    • 思路就是给一个背包和给多个物品,问装满背包有多少种排列(每个物品可以重复拿取)
  • 视频讲解关键点总结
    • 我的思路没有问题,需要注意的是,不同的内外循环顺序会带来不同的结果,一种计算的是组合数,一种计算的是排列数(相同的元素,不同的顺序也视为不同)
      • 先遍历物品,再遍历背包容量,得到的结果是组合数——因为此时在不同种背包容量的情况里,都是先放进物品1再放进物品2,不会出现先放2再放1的情况,此时得到的组合之间不会出现顺序不同、元素相同的情况
      • 先遍历背包容量,再遍历物品,得到的结果是排列数——因为此时在背包容量递增的过程中,物品1和物品2放入的先后顺序不一定,可能先放了1也可能先放了2,因此集合之间会出现顺序不同、元素相同的情况,也就是得到的结果是排列数
  • 我的思路的问题
  • 代码书写问题
  • 可执行代码
class Solution:def combinationSum4(self, nums: List[int], target: int) -> int:dp = [0] * (target + 1)dp[0] = 1for j in range(1, target + 1):for i in range(len(nums)):if j >= nums[i]:dp[j] += dp[j - nums[i]]return dp[-1]
http://www.lryc.cn/news/316875.html

相关文章:

  • C语言每日一题(63)复写零
  • ElasticSearch聚合查询
  • 【毕设级项目】基于AI技术的多功能消防机器人(完整工程资料源码)
  • 【一】【设计模式】类关系UML图
  • 【DevOps基础篇】容器化架构基础设施监控方案
  • 【QT】文件流操作(QTextStream/QDataStream)
  • CentOS 7 devtoolset编译addressSanitizer版本失败的问题解决
  • ubuntu2004桌面系统英伟达显卡驱动安装方法
  • Java通过Excel批量上传数据!!!
  • 【PyQT/Pysider】控件背景渐变
  • ChatGPT-4 VS 文心一言4.0
  • MYSQL------从概述到DQL
  • MATLAB算法实战应用案例精讲-【图像处理】图像识别(基础篇)(二)
  • Leetcode 3.12
  • 【天池课堂】零基础入门数据挖掘-课程汇总
  • 表单进阶(3)-上传文件和隐藏字段
  • LLM(大语言模型)常用评测指标-MAP@R
  • 腾讯面经学习笔记
  • 北京某中厂凉经
  • 离线数仓(五)【数据仓库建模】
  • python | 类与对象
  • 基于Qt 和python 的自动升级功能
  • 【论文阅读】IEEE Access 2019 BadNets:评估深度神经网络的后门攻击
  • Unity 让角色动起来(动画控制器)
  • ubuntu22.04环境中安装pylint
  • 主流数据库的区别
  • veeam备份基础
  • Flink并行度
  • 这届留学生是懂作弊的,ChatGPT震惊教授一整年!
  • CVE-2023-38836 BoidCMSv.2.0.0 后台文件上传漏洞