DAY43 完全背包理论基础 + 518.零钱兑换II

news/2025/2/14 7:32:12/

完全背包

有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。

完全背包和01背包问题唯一不同的地方就是,每种物品有无限件

假设背包最大重量为4。物品为:

重量价值
物品0115
物品1320
物品2430

每件商品都有无限个。

因此在01背包中,我们为了使每件物品只被加入背包一次,在内层遍历的时候我们选择了倒序遍历。但是在完全背包中,物品的数量是无限的,因此可以被添加多次,所以要从小到大去遍历。

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品for(int j = weight[i]; j <= bagWeight ; j++) { // 遍历背包容量dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);}
}

其实还有一个很重要的问题,为什么遍历物品在外层循环,遍历背包容量在内层循环?

01背包中二维dp数组的两个for遍历的先后循序是可以颠倒了,一维dp数组的两个for循环先后循序一定是先遍历物品,再遍历背包容量。

在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序是无所谓的!

因为dp[j] 是根据 下标j之前所对应的dp[j]计算出来的。 只要保证下标j之前的dp[j]都是经过计算的就可以了。

遍历物品在外层循环,遍历背包容量在内层循环,状态如图:

遍历背包容量在外层循环,遍历物品在内层循环,状态如图:

 

看了这两个图,大家就会理解,完全背包中,两个for循环的先后循序,都不影响计算dp[j]所需要的值(这个值就是下标j之前所对应的dp[j])。

 518. 零钱兑换II

题目要求:给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

示例 1:

  • 输入: amount = 5, coins = [1, 2, 5]
  • 输出: 4

解释: 有四种方式可以凑成总金额:

  • 5=5
  • 5=2+2+1
  • 5=2+1+1+1
  • 5=1+1+1+1+1

思路

完全背包问题,容量就是amount,物品是coins。dp[i]表示组成i大小背包容量的方式数量。同时题目中强调凑成总金额的是组合,所以不强调元素之间的顺序。

状态转移方程就是:dp[i] += dp[j-coins[i]],与昨天遇到的题目相同。

这个递推公式大家应该不陌生了,我在讲解01背包题目的时候在这篇494. 目标和 (opens new window)中就讲解了,求装满背包有几种方法,公式都是:dp[j] += dp[j - nums[i]];

class Solution {
public:int change(int amount, vector<int>& coins) {vector<int> dp(amount+1, 0);dp[0] = 1;for (int i = 0; i < coins.size(); ++i) {for (int j = coins[i]; j <= amount; ++j) {dp[j] += dp[j - coins[i]];}}return dp[amount];}
};

377. 组合总和 Ⅳ

题目要求:给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。

示例:

  • nums = [1, 2, 3]
  • target = 4

所有可能的组合为: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1)

请注意,顺序不同的序列被视作不同的组合。

因此输出为 7。

思路

与上一个题目类似,但是本题是排序,强调序列的顺序。而上一个题目是组合,不强调顺序。

  • 确定遍历顺序

个数可以不限使用,说明这是一个完全背包。

得到的集合是排列,说明需要考虑元素之间的顺序。

本题要求的是排列,那么这个for循环嵌套的顺序可以有说法了。、

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

如果把遍历nums(物品)放在外循环,遍历target的作为内循环的话,举一个例子:计算dp[4]的时候,结果集只有 {1,3} 这样的集合,不会有{3,1}这样的集合,因为nums遍历放在外层,3只能出现在1后面!

所以本题遍历顺序最终遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历

class Solution {
public:int combinationSum4(vector<int>& nums, int target) {vector<int> dp(target+1, 0);dp[0] = 1;for (int i = 0; i <= target; ++i) { // 遍历背包for (int j = 0; j < nums.size(); ++j) { // 遍历物品if (i - nums[j] >= 0 && dp[i] < INT_MAX - dp[i - nums[j]]) {dp[i] += dp[i - nums[j]];}}}return dp[target];}
};
  • 时间复杂度: O(target * n),其中 n 为 nums 的长度
  • 空间复杂度: O(target)

C++测试用例有两个数相加超过int的数据,所以需要在if里加上dp[i] < INT_MAX - dp[i - num]。

  • Day43总结
  • 背包问题的遍历顺序是一门学问,01背包物品只能用一次外层是物品内层倒叙是容量;
  • 完全背包的组合问题不强调顺序,物品可以用无限次,外层是物品,内层是背包容积的正序;
  • 完全背包的排列问题,强调顺序,外层是背包容积,内层是物品,这样大编号的物品也可以出现在前面。

http://www.ppmy.cn/news/1196812.html

相关文章

讲座分享|《追AI的人》——中国科学技术大学张卫明教授分享《人工智能背景下的数字水印》

本篇博客记录 2023年11月1日 《人工智能背景下的数字水印》 讲座笔记。 先来明确一下水印在信息隐藏中的定位&#xff0c;如下图&#xff1a; 目录 概述AI for Watermark图像传统攻击方式&#xff08;如JPEG压缩&#xff09;跨媒介攻击方式&#xff08;屏摄&#xff09; 文档水…

Jetpack:028-Jetpack中的Card

文章目录 1. 概念介绍2. 使用方法2.1 主要类型2.2 其它类型 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中Switch相关的内容&#xff0c;本章回中 主要介绍Card。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我们在本章回中介…

orangepi zero2 全志H616 SSD1306 OLED屏幕测试程序 (已附源码)

orangepi zero2 H616 SSD1306 OLED屏幕测试程序 orangepi zero2 配置wiringpi 库后&#xff0c;突发奇想构建一个测试oled屏幕的程序&#xff0c;放一个蜗牛每次移动一个像素点&#xff0c;实时显示蜗牛的步数&#xff0c;后面要显示其他内容在此代码上修改即可&#xff0c;如…

Python基础入门例程32-NP32 牛牛的加减器(运算符)

最近的博文&#xff1a; Python基础入门例程31-NP31 团队分组&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程30-NP30 用列表实现队列&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程29-NP29 用列表实现栈&#xff08;列表&#xff09;-CSDN博客 目录…

MyBatis 详解

目录 1.MyBatis 框架的搭建 1.1 创建数据库和表 1.2 添加 MyBatis 依赖 1.3 设置 MyBatis 配置 1.3.1 设置数据库的连接信息 1.3.2 设置 XML 保存路径和命名格式 1.4 根据 MyBatis 写法完成数据库得操作 1.4.1 定义接口 1.4.2 使用 XML 实现接口 2.MyBatis查询操作 …

配置Raspberry自动连接WIFI,在无法查看路由器的校园网情况下使用自己电脑热点

1、开启电脑热点&#xff0c;并共享电脑WLAN2 打开控制面板->网络和Internet->网络连接 选择自己的校园网&#xff0c;我这里是WLAN2&#xff0c;右键属性&#xff0c;如下操作&#xff1a; 如果没有看到 本地连接*10类似的图标 则按如下操作&#xff1a;winx键&#x…

Day13反转链表两两交换链表中的节点删除链表的倒数第N个节点链表相交环形链表II

反转链表 struct ListNode* reverseList(struct ListNode* head){struct ListNode* preNULL;while(head){struct ListNode* temphead->next;head->nextpre;prehead;headtemp;}return pre; }两两交换链表中的节点 struct ListNode* swapPairs(struct ListNode* head){st…

ConnectionError: HTTPSConnectionPool

ConnectionError: HTTPSConnectionPool(host‘zbbfxstatic.figtingdream.com’, port443): Max retries exceeded with url: /api/cache (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x00000249795AD9A0>: Failed to establish a ne…