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

news2025/1/24 14:01:10

完全背包:一个物品可以使用无数次,将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.coloradmin.cn/o/1268185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统

ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统 概述 在前述章节我们讲述了在网页端控制多个 GPIO 的案例。当程序开始变得复杂&#xff0c;让一些功能“自动起来”是一个好的选择。 在前面的示例中&#xff0c;我们需要在后端为每个前端代码的 URL 指定一个对…

SQL server界面操作链接服务器

1.打开链接服务器&#xff0c;右击连接服务器“新建链接服务器” 2.输入链接服务器名称和数据源 3.安全性中输入密码建立远程连接&#xff0c;点击确定&#xff1a; 4.打开新建的连接服务器&#xff0c;测试连接&#xff1a; 注意:链接服务器必须在局域网执行&#xff0c;不是同…

不同类型的开源许可证

不同类型的开源许可证 什么是开源许可证 最简单的解释是&#xff0c;开源许可证是计算机软件和其他产品的许可证&#xff0c;允许在定义的条款和条件下使用、修改或共享源代码、蓝图或设计。开源并不意味着该软件可以根据需要使用、复制、修改和分发。根据开源许可证的类型&a…

荣耀IPO站上新起点:市场望眼欲穿,发展未来可期

撰稿|行星 来源|贝多财经 荣耀手机HONOR&#xff08;简称“荣耀”&#xff09;IPO上市一事有了新的进展。 近日&#xff0c;荣耀终端有限公司发布董事会公告称&#xff0c;为实现公司下一阶段的战略发展&#xff0c;该公司将不断优化股权结构&#xff0c;吸引多元化资本进入…

面试题:海量PDF的OCR处理思路

关键点&#xff1a; 1000wPDF&#xff1a;数据量非常大。3天处理完&#xff1a;有时间限制。一篇PDF1~10s&#xff1a;可能需要以最高10s去做计算&#xff0c;这样时间才能保证留有富余。要求资源最大化利用&#xff1a;也就是尽可能节省服务器资源&#xff0c;能复用尽量复用&…

一切为了应用!九章云极DataCanvas大模型系列成果重磅发布!

11月21日&#xff0c;「筑基赋能 智向未来」九章云极DataCanvas大模型系列成果发布会&#xff08;以下简称“发布会”&#xff09;在北京重磅召开&#xff0c;本次成果发布距离今年6月30日DataCanvas Alaya九章元识大模型公布仅4个多月&#xff0c;是九章云极DataCanvas公司大模…

用flutter 写一个专属于儿子的听书的app

背景: 儿子最近喜欢上了用儿童手表听故事&#xff0c;但是手表边里的应用免费内容很少&#xff0c;会员一年要300多&#xff0c;这么一笔巨款&#xff0c;怎能承担的起&#xff0c;所以打算自己开发一个专属于儿子的听书app。 最终效果&#xff1a; 架构&#xff1a; 后端由两…

stm32 计数模式

计数模式 但是对于通用定时器而言&#xff0c;计数器的计数模式不止向上计数这一种。上文基本定时器中计数器的计数模式都是向上计数的模式。 向上计数模式&#xff1a;计数器从0开始&#xff0c;向上自增&#xff0c;计到和自动重装寄存器的目标值相等时&#xff0c;计数器清…

拒绝随波逐流!设计与实现可控的水下机器人

这个“长着三个触角”的水下机器人看上去是不是很萌&#xff1f;它使用的是一种新型的由三个球形磁耦合矢量推进器组成的推进系统。与传统的水下机器人使用多个固定推进器来实现多自由度&#xff08;DOF&#xff09;推进相比&#xff0c;矢量推进器具有多自由度、寄生推力小&am…

WARNING: Access control is not enabled for the database.

MongoDB shell version v3.4.24 WARNING: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted. 1)未启用访问控制 2)读写访问不受限制 D:\MongoDB\Server\3.4\bin>mongo MongoDB shell version v3.4.24 c…

BUUCTF刷题之路-pwn-ciscn_2019_n_81

这 题查保护的时候吓了一跳&#xff0c;保护全开。脑子飞速旋转是要我绕过canary,PIE然后再利用栈溢出劫持程序流吗&#xff1a; 然后扔进IDA中查看下大致流程&#xff1a; 大致看出var是个数组&#xff0c;当var[13]17的时候就会得到system。那还不简单直接写payload: from p…

2021年1月19日 Go生态洞察:Go命令行路径安全性的提升

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

freertos任务调度机制深度分析(以RISC-V架构为例)

1、前言 本文是以RISC-V架构为例进行讲解&#xff0c;在汇编代码层面和ARM架构不一样&#xff0c;但是整体框架是一样的侧重任务调度底层机制讲解&#xff0c;讲解代码只保留了基本功能&#xff0c;可配置的功能基本都已经删除本文是以可抢占式调度机制进行讲解RISC-V架构只支持…

【Web安全】拿到phpMyAdmin如何获取权限

文章目录 1、outfile写一句话2、general_log_file写一句话 通过弱口令拿到进到phpMyAdmin页面如何才能获取权限 1、outfile写一句话 尝试执行outfile语句写入一句话木马 select "<?php eval($_REQUEST[6868])?>" into outfile "C:\\phpStudy\\WWW\\p…

WSDM 2024 | LLMs辅助基于内容的推荐系统增强BPR训练数据

本文提出了一种简单而有效的基于LLMs的图数据增强策略&#xff0c;称为LLMRec&#xff0c;以增强基于内容的推荐系统。LLMRec包含三种数据增强策略和两种去噪策略。数据增强策略包括从文本自然语言的角度挖掘潜在的协同信号, 构建用户画像(LLM-based), 并强化item side informa…

JavaScript 特殊数据类型

JavaScript 特殊数据类型 目录 JavaScript 特殊数据类型 一、空值&#xff08;null型&#xff09; 二、未定义值&#xff08;undefined型&#xff09; 三、转义字符 JavaScript的特殊数据类型有3种&#xff1a; &#xff08;1&#xff09;空值&#xff08;null型&#xf…

【hacker送书第6期】深入理解Java核心技术

第6期图书推荐 内容简介作者简介精彩书评参与方式 内容简介 《深入理解Java核心技术&#xff1a;写给Java工程师的干货笔记&#xff08;基础篇&#xff09;》是《Java工程师成神之路》系列的第一本&#xff0c;主要聚焦于Java开发者必备的Java核心基础知识。全书共23章&#xf…

Go语言基础:包、函数、语句和注释解析

一个 Go 文件包含以下几个部分&#xff1a; 包声明导入包函数语句和表达式 看下面的代码&#xff0c;更好地理解它&#xff1a; 例子 package mainimport "fmt"func main() { fmt.Println("Hello World!") }例子解释 第 1 行&#xff1a; 在 Go 中&am…

nodejs 沙盒逃逸

1.[GFCTF 2021]ez_calc 一道很有意思的一道nodejs的题 沙箱逃逸和绕过&#xff1a; F12 看源码 if(req.body.username.toLowerCase() ! admin && req.body.username.toUpperCase() ADMIN && req.body.passwd admin123){ // 登录成功&am…

sqli-labs靶场详解(less32-less37)

宽字节注入 原理在下方 目录 less-32 less-33 less-34 less-35 less-36 less-37 less-32 正常页面 ?id1 下面有提示 获取到了Hint: The Query String you input is escaped as : 1\ ?id1 看来是把参数中的非法字符就加上了转义 从而在数据库中只能把单引号当成普通的字…