代码随想录算法训练营第三十八天|完全背包,518. 零钱兑换 II ,377. 组合总和 Ⅳ

完全背包

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

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

公式推导:01背包问题是从二维数组压缩到一维数组,由于一维数组要保证每次取得物品不重合,遍历顺序也就变成了从后向前遍历。但是完全背包问题每种物品数量不限制数量,也就是说不需要防止重合情况,那问题就变成了一维数组或者说是滚动数组从前往后遍历

首先再回顾一下01背包的核心代码

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

而完全背包的物品是可以添加多次的,所以要从小到大去遍历

// 先遍历物品,再遍历背包
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]);}
}

 注意:这里j什么要从weight[i]开始,因为当j小于weight[i]时,也就是当前容量不足以装下当前第i个物品,所以每次在遍历开始都要从weight[i]开始。

dp数组初始化:dp[j]=0,也就是没放物品时,不管容量多大,价值都是0;

举例推导dp公式:

背包最大重量为4。

物品为:

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

每件商品都有无限个!

问背包能背的物品最大价值是多少?

我们来走一遍流程:

只可以选物品0时:随着容量变大,不断放进物品0就行,直到装满,结果就出来了 ;

可以选物品0和物品1时:首先容量0-2时,物品1放不进,所有直接将上一步结果放入,这一步其实也就是解释了为什么二维数组可以被压缩,也解释了为什么j要从weight[i]开始;

        牢记dp[j]是代表j容量的背包填满,最大价值是多少。

 当容量变成3(j=weight[i])以后,dp[j]发生了什么,dp[j]有两个来源:

①不加入物品1,那就是和上一步结果一样,所以取dp[3];

②加入物品1,首先容量得腾出位置来放物品1,所以3-weight[1],也就是容量变成1了,当j=1时,dp[1]=15(最大价值是15),再加上物品1的价值value[1]=20,所以dp[3-weight[1]]+value[1]。进行最后一步,选出dp[3]和dp[3-weight[1]]+value[1]的最大值,就是当前容量填满放进去物品的最大价值。

        最后,j=4或者物品2也在选择范围时,就可以用公式:

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

完整代码: 注意这里先开始遍历物品再开始遍历背包容量,反过来也可以,区别于一维01背包。

void test_CompletePack() {vector<int> weight = {1, 3, 4};vector<int> value = {15, 20, 30};int bagWeight = 4;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]);}}return dp[bagWeight];
}

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

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数。

示例 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

示例 2:

输入:amount = 3, coins = [2]
输出:0
解释:只用面额 2 的硬币不能凑成总金额 3 。

思路:完全背包问题,amount就是背包容量,coins就是可以选择的物品。

解决:动态规划五部步曲

        1.确定dp[j]的含义;

        dp[j]:凑成总金额j的货币组合数为dp[j]。注意这里dp[j]求得是组合数,不是硬币的总额。

        2.确定递推公式;

        和494.目标和类似,dp[j]+=dp[j-coins[i]]

        3.确定dp初始化;

        还是和494.目标和类似,dp[0]=1;

代码随想录算法训练营第三十七天|1049. 最后一块石头的重量 II ,494. 目标和,474.一和零-CSDN博客

        4.确定遍历顺序;

        先遍历硬币,再遍历金额,里层遍历从前向后遍历,因为硬币可以重复用。

        5.举例推导dp数组。

输入: amount = 5, coins = [1, 2, 5] ,dp状态图如下:

代码:

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. 组合总和 Ⅳ - 力扣(LeetCode)

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

示例 1:

输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。

思路:这里nums是可以重复的,可以转换成完全背包问题。

        ①物品:这里物品就是nums里面元素;

        ②背包:就是组合,但是这里要求的是组合数量,所以dp数组里不是放价值,是放组合的数量;

        拿示例1来说,就是需要背包物品总价值为4(j=4),从nums中选物品(可以重复)放入背包,有7种组合dp[j]。

解决:动态规划五步曲

        1.确定dp[j]含义;

        dp[j]就表示目标数为j的组合有dp[j]种。

        2.确定递推公式;

        和上题一样,dp[j]=dp[j]+dp[j-nums[i]]

        3.确定dp初始化;

        dp[j]初始都为0,dp[0]=1。

        4.确定遍历顺序;

                ①由于可以重复选取元素,所以这是一个完全背包问题

                ②其次组合顺序不同也算一种新组合,题目要的其实是排列

                循环方式就两种:外循环物品,内循环目标数;外循环目标数,内循环物品。

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

        所以本题遍历顺序最终遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历。同样举个例子,当j=3时,我可以先取1再取2,或者先取2再取1,因为当前循环target没变,是通过遍历nums数组去组合。

        5.举例推导dp数组。

代码:

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

class Solution {
public:int combinationSum4(vector<int>& nums, int target) {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]>=0&&dp[j] < INT_MAX - dp[j - nums[i]]){dp[j]=dp[j]+dp[j-nums[i]];}}}return dp[target];}
};

        防止数组越界 要判断j-nums[i]>=0。

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

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

相关文章

机器学习硬件十年:性能变迁与趋势

本文分析了机器学习硬件性能的最新趋势&#xff0c;重点关注不同GPU和加速器的计算性能、内存、互连带宽、性价比和能效等指标。这篇分析旨在提供关于ML硬件能力及其瓶颈的全面视图。本文作者来自调研机构Epoch&#xff0c;致力于研究AI发展轨迹与治理的关键问题和趋势。 &…

小红书蒲公英平台开通后,有哪些注意的地方,以及如何进行报价?

今天来给大家聊聊当小红书账号过1000粉后&#xff0c;开通蒲公英需要注意的事项。 蒲公英平台是小红书APP中的一个专为内容创作者设计的平台。它为品牌和创作者提供了一个完整的服务流程&#xff0c;包括内容的创作、推广、互动以及转换等多个方面。 2.蒲公英平台的主要功能 &…

第一启富金:新添澳大利亚(ASIC)牌照

第一启富金&#xff1a;澳大利亞證券及投資委員會&#xff08;ASIC&#xff09; GOLDWELL GLOBAL PTY LTD 是 WHOLESALE INVESTOR SERVICES PTY LTD&#xff08;CAR 編號 001304943&#xff09;的企業授權代表開發澳大利亞客戶&#xff0c;WHOLESALE INVESTOR SERVICES PTY LT…

前端学习系列之CSS

目录 CSS 简介 发展史 优势 基本语法 引用方式 内部样式 行内样式 外部样式 选择器 id选择器 class选择器 标签选择器 子代选择器 后代选择器 相邻兄弟选择器 后续兄弟选择器 交集选择器 并集选择器 通配符选择器 伪类选择器 属性选择器 CSS基本属性 优…

Java_LinkedList链表详解

目录 前言 ArrayList的缺陷 链表 链表的概念及结构 链表的种类 1.单向或双向 2.带头或不带头 3.循环或不循环 LinkedList的使用 什么是LinkedList LinkedList的使用 LinkedList的构造 LinkedList的其他常用方法介绍 LinkedList的遍历 ArrayList和LinkedList的…

深入了解Java 8日期时间新玩法之Year、YearMonth、MonthDay、DayOfWeek

推荐语 在这篇文章中&#xff0c;我们将深入探讨Java 8中Year、YearMonth、MonthDay和DayOfWeek类的功能和使用方法。这些类是在Java 8中引入的新的日期时间API的一部分&#xff0c;它们为我们提供了更灵活、更易用的日期和时间处理能力。 尽管这些类在Java 8中已经出现&…

跨境电商系统搭建 无货源系统对接API 反向代购系统

跨境电商系统是为国外的客户代购中国商品的系统&#xff0c;系统实现与国内电商API对接&#xff0c;客户可直接在系统中搜索国内电商平台的商品。查看演示网站 一级功能二级功能 标准版 高级版 企业版 企业旗舰版 大客户尊享版 标准版高级版企业版企业旗舰版大客户尊享版 前台主…

泽攸科技二维材料转移台的应用场景及优势

随着二维材料的广泛研究和各种潜在应用的开发&#xff0c;对于二维材料样品的精密操控与转移的需求日益增加。特别是一些新型二维材料的制备和器件集成制备中&#xff0c;需要在显微镜下对样品进行观察与定位&#xff0c;并能够在微米甚至纳米量级上精确移動和转移样品。 传统…

溯源取证-WEB流量分析-简单

话不多说直接干&#xff1a; 题干&#xff1a; 开发团队在公司的一个 Web 服务器上发现了异常文件&#xff0c;开发团队怀疑该服务器上存在潜在的恶意活动&#xff0c;网络团队准备了一个包含关键网络流量的 pcap 文件&#xff0c;供安全团队分析&#xff0c;而你的任务是分析…

数学建模-二氧化碳排放及时空分布测度

二氧化碳排放及时空分布测度 整体求解过程概述(摘要) 面临全球气候变化的巨大挑战&#xff0c;我国积极响应《巴黎协定》的号召&#xff0c;提出“2030年前碳达峰&#xff0c;2060 年前实现碳中和”的碳排放发展目标&#xff0c;并将碳中和相关工作作为 2021 年的重点任务之一…

Selenium自动化测试总结

一、Selenium自动化测试&#xff08;基于python&#xff09; 1、Selenium简介&#xff1a; 1.1 Selenium是一款主要用于Web应用程序自动化测试的工具集合。Selenium测试直接运行在浏览器中&#xff0c;本质是通过驱动浏览器&#xff0c;模拟浏览器的操作&#xff0c;比如跳转、…

浪潮信息KeyarchOS——保卫数字未来的安全防御利器

浪潮信息KeyarchOS——保卫数字未来的安全防御利器 前言 众所周知&#xff0c;目前流行的操作系统有10余种&#xff0c;每一款操作系统都有自己的特点。作为使用者&#xff0c;我们该如何选择操作系统。如果你偏重操作系统的安全可信和稳定高效&#xff0c;我推荐你使用浪潮信…