C++ day44完全背包问题 零钱兑换Ⅱ 组合总和Ⅳ

完全背包:一个物品可以使用无数次,将01背包中倒序遍历背包变成正序遍历背包

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

先遍历物品,后遍历背包可以;先遍历背包,后遍历物品也可以,因为dp[j] 是根据 下标j之前所对应的dp[j]计算出来的,只要保证下标j之前的dp[j]都是经过计算的就可以了。

纯完全背包问题题目链接:完全背包

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

代码1(先正序遍历物品,后正序遍历背包)

void full_backbag(vector<int>weight,vector<int> value,int bagweight){//初始化dp数组,定义dp数组vector<int> dp(bagweight+1,0);//递推。先正序遍历物品,后正序遍历背包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]);}}cout << dp[bagweight] << endl;
}

代码2(先正序遍历背包,后正序遍历物品)

void full_backbag(vector<int>weight,vector<int> value,int bagweight){//初始化dp数组,定义dp数组vector<int> dp(bagweight+1,0);//递推,先正序遍历背包,后正序遍历物品for(int j=0;j<=bagweight;j++){for(int i=0;i<weight.size();i++){if(j>=weight[i]) dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);}}cout << dp[bagweight] << endl;
}

可以出一道面试题了,就是纯完全背包,要求先用二维dp数组实现,然后再用一维dp数组实现,最后再问,两个for循环的先后是否可以颠倒?为什么?

题目2:518  零钱兑换Ⅱ

题目链接:零钱兑换Ⅱ

对题目的理解

整数数组coins表示不同面额的硬币,整数amount表示总金额

返回可以凑成总金额的硬币组合有多少种,如果无法凑出,则返回0,假设每一种面额的硬币有无限个  数据保证结果是带符号32位整数,注意求的是组合,不是排列

coins中至少有1个硬币,最多有300个硬币;硬币的面额至少是1,最大是5000,且记录的coins中的数值互不相同   总金额在0~5000之间(闭区间)

每个物品可以使用无限次,是完全背包问题,但是本题和纯完全背包不一样纯完全背包是凑成背包最大价值是多少,而本题是要求凑成总金额的物品组合个数!

动规五部曲

1)明确dp数组及下标的含义

dp[j]:装满容量为j的背包有dp[j]种方法  ,最终求解dp[amount]

2)递推公式

dp[j]+=dp[j-coins[i]]由目标和那道题得到

3)dp数组初始化

dp[0]=1 根据递推公式得到,如果dp[0] = 0 的话,后面所有推导出来的值都是0了。其他 非零下标对应的dp[j]初始化为0,这样累加的时候才不会影响结果

4)遍历顺序(难点)

纯完全背包求得装满背包的最大价值是多少,和凑成总和的元素有没有顺序没关系,即:有顺序也行,没有顺序也行!能凑成总和就行

本题要求凑成总和的组合数,元素之间明确要求没有顺序,那么两个for循环就有顺序请求了

!!!先正序遍历物品,后正序遍历背包(组合)

这个是从前往后考虑每一个硬币,前面的硬币在之后不会重复,后面的硬币只在后面出现,所以没有重复的组合,所以这个是针对组合的,考虑容量的时候,后面只会考虑在前面硬币的基础上增加后面的硬币,而不会在后面的硬币不足的情况下,增加前面的硬币

!!!先正序遍历背包,后正序遍历物品(排列)

上述这个圈出来的3求解的时候,多计算了一次,因为前面计算coins[0]=1时,容量为3那个已经计算了{1,1,1}和{1,2}的组合,而下面在coins[1]=2,容量为3时,又计算了一次{2,1}的组合,所以这个是针对排列的

5)打印dp数组

代码

class Solution {
public:int change(int amount, vector<int>& coins) {//定义并初始化dp数组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];}
};
  • 时间复杂度: O(mn),其中 m 是amount,n 是 coins 的长度
  • 空间复杂度: O(m)

题目3:377  组合总和Ⅳ

题目链接:组合总和Ⅳ

对题目的理解

整数数组nums由不同整数组成,找出nums中总和为target的元素的组合个数(nums中的元素是可以重复使用的)但是本题求的是集合的个数,是一种排列(nums[i]>=1,nums数组中至少有一个元素)

本题元素可以重复使用,完全背包问题

如果本题要把排列都列出来的话,只能使用回溯算法爆搜

动规五部曲

1)dp数组及下标的含义

总和为j的背包有dp[j]种排列   最终求的是dp[target]

2)   递推公式

dp[j] += dp[j-nums[i]]

3)dp数组初始化

根据递推公式的累加,可推出dp[0]=1 ,不然,初始化为0的话,dp数组全为0; 递推公式是累加的,所以其余非零下标的dp[j]均初始化为0,以免覆盖计算的dp结果

4)遍历顺序

由于题目要求的是排列,所以先遍历背包后遍历物品

5)打印dp数组

class Solution {
public:int combinationSum4(vector<int>& nums, int target) {//定义并初始化dp数组vector<int> dp(target+1,0);dp[0] = 1;//递推,先正序遍历背包,后正序遍历物品,得到排列for(int j=0;j<=target;j++){for(int i=0;i<nums.size();i++){if(j>=nums[i] && dp[j]<INT_MAX-dp[j-nums[i]]) dp[j] += dp[j-nums[i]];}}return dp[target];}
};
  • 时间复杂度: O(target * n),其中 n 为 nums 的长度
  • 空间复杂度: O(target)

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

求装满背包有几种方法,递归公式都是一样的,没有什么差别,但关键在于遍历顺序!

扩展

(面试)本题可延伸至进化版的爬楼梯:

一步可以爬几个台阶,相当于组合总和Ⅳ的nums数组中每一个物品[1,2,3,....,m],爬到楼顶是n,n就是target,求爬到楼顶有多少种方法(强调元素的顺序),即装满背包有多少种方法  ,代码和组合总和IV一样  完全背包

假如一步可以爬m个台阶,爬到楼顶有多少种方法?求的是排列数,还是组合数?

遍历顺序可不可以颠倒,如果颠倒,求的是什么场景,没有颠倒,求的又是什么场景?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/231338.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode [简单](非递归)二叉树的中序遍历

遍历左孩子&#xff0c;将他们放进栈中&#xff0c;左边走到尽头&#xff0c;出栈&#xff0c;root变为栈顶元素&#xff0c;存值&#xff0c;向右边走一个 再次遍历左孩子&#xff0c;将他们放入栈中&#xff0c;如果没有左孩子了&#xff0c;就出栈&#xff0c;root变为栈顶…

网页能做二维码吗?1分钟学会链接转码的方法

想要将链接做成二维码图片&#xff0c;让他人通过扫码跳转链接以提高网页的传播性&#xff0c;是现在很常用的一种手段。主要在于二维码是现在最常用的一种展现方式&#xff0c;更加符合现在人的行为习惯&#xff0c;那么网址二维码该如何操作呢&#xff1f;今天小编给大家讲解…

网络层协议-IP协议

目录 基本概念IP协议格式分片与组装分片组装 网段划分特殊的IP地址IP地址的数量限制私有IP地址和公网IP地址路由 基本概念 TCP作为传输层控制协议&#xff0c;其保证的是数据传输的可靠性和传输效率&#xff0c;但TCP提供的仅仅是数据传输的策略&#xff0c;而真正负责数据在网…

DCGAN 使用指南:将卷积神经网络和对抗网络结合,适用于生成小尺寸的图像

DCGAN 使用指南&#xff1a;将卷积神经网络和对抗网络结合 网络结构细节设计 论文地址&#xff1a;https://arxiv.org/abs/1511.06434 项目代码&#xff1a;https://github.com/tensorlayer/DCGAN.git DCGAN 适用于生成小尺寸的图像&#xff0c;并且具有简单易用的优势 Styl…

了解HashMap底层数据结构吗

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

Spark将execl表格文件导入到mysql中

实现代码 excel所需的pom依赖 案例实现 实现代码 package excel_mysqlimport org.apache.spark.sql.SparkSession import java.util.Propertiesobject t1 {def main(args: Array[String]): Unit {val spark SparkSession.builder().appName("ExcelToMySQL") /…

视频剪辑技巧:批量剪辑新思路,AI智剪来助阵

在视频制作过程中&#xff0c;剪辑是一项至关重要的任务。然而&#xff0c;对于许多创作者来说&#xff0c;批量剪辑视频是一项耗时且繁琐的工作。传统的批量剪辑方法通常要创作者逐个打开视频文件&#xff0c;进行剪辑、调整色彩等操作。这种方法不仅效率低下&#xff0c;而且…

zookeeper集群(很少用)+kafka集群(常用)

一、zookeeper zookeeperkafka&#xff08;2.7.0版本&#xff09; kafka&#xff08;3.4.1版本&#xff09;不依赖于zookeeper 1、定义&#xff1a;zookeeper开源&#xff0c;分布式架构&#xff0c;提供协调服务&#xff08;Apache项目&#xff09;&#xff0c;基于观察者模…

spring security 艰苦学习中

一、初次感知 1.jwt工具类 密钥secret 有点意思。 2.PasswordEncoder 对密码进行加密&#xff0c;在配置类中返回bean. 下面这个关于加密和解密的东西是有误导性的。

基础课13——知识库

1.知识库的概念、特点与功能 智能客服中的知识库是一个以知识为基础的系统&#xff0c;可以明确地表达与实际问题相对应的知识&#xff0c;并构成相对独立的程序行为主体&#xff0c;有利于有效、准确地解决实际问题。它储存着机器人对所有信息的认知概念和理解&#xff0c;这…

【C++初阶】:简单的图书管理系统(可保存,完整源代码)

图书管理系统 library.h #include<iostream> #include<string> #include<vector> using namespace std;/****************************************************************公共类**********************************************************************…

BIO、NIO、selector、Netty代码Demo示例

文章目录 &#xff08;一&#xff09;BIO&#xff08;Blocking I/O 阻塞I/O&#xff09;&#xff08;二&#xff09;NIO&#xff08;Non-Blocking I/O 非阻塞I/O&#xff09;&#xff08;三&#xff09;IO多路复用--Selector&#xff08;四&#xff09;Netty &#xff08;一&am…