Day37--动态规划--52. 携带研究材料(卡码网),518. 零钱兑换 II,377. 组合总和 Ⅳ,57. 爬楼梯(卡码网)

Day37–动态规划–52. 携带研究材料(卡码网),518. 零钱兑换 II,377. 组合总和 Ⅳ,57. 爬楼梯(卡码网)

本文全部都是 ” 完全背包 “ 问题,从零到入坑,从入坑到爬出来。

本文的精华在:《为什么是“先遍历背包,后遍历数字”?》非常详细地讲解了,为什么先遍历数字,后遍历背包——是组合数。先遍历背包,后遍历数字——是排列数。

52. 携带研究材料(卡码网)

思路:

  1. 确定dp数组含义:dp[i][j] 表示从下标为[0-i]的物品,每个物品可以取无限次,放进容量为j的背包,价值总和最大是多少
  2. 确定递推公式:(和01背包相似,所以只讲区别)
    • 在01背包中,每个物品只有一个,既然空出物品1,那背包中也不会再有物品1。所以空出来之后,去上一层找,即dp[i-1][j-weight[i]]
    • 而在完全背包中,每个物品可以无限取,即使空出物品1空间重量,那背包中也可能还有物品1。所以空出来之后,要从本层取,即dp[i][j-weight[i]]
    • 得出递推公式:dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);
  3. 初始化:初始化第一行,从背包能放得下weight[0]这个东西开始,往后遍历。能放多少是多少。
  4. 确定遍历顺序,每个dp[i][j],都要靠左边,上边的值确定数据。所以是从上往下,从左往右。
import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int bagSize = in.nextInt();int[] weight = new int[n];int[] value = new int[n];for (int i = 0; i < n; i++) {weight[i] = in.nextInt();value[i] = in.nextInt();}int[][] dp = new int[n][bagSize + 1];// 初始化第一行,从背包能放得下weight[0]这个东西开始,往后遍历for (int j = weight[0]; j <= bagSize; j++) {dp[0][j] = dp[0][j - weight[0]] + value[0];}// 动态规划for (int i = 1; i < n; i++) {for (int j = 1; j <= bagSize; j++) {// 当前背包放不下weight[i],直接等于上一层if (j < weight[i]) {dp[i][j] = dp[i - 1][j];} else {// 这里的递归公式,与01背包不同。要空出weight[i]的时候,看的是本层的dp// 区别在于,这里是dp[i][j - weight[i]],而01背包是:dp[i-1][j - weight[i]]dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);}}}System.out.println(dp[n - 1][bagSize]);}
}

518. 零钱兑换 II

思路:二维dp数组

  1. 确定dp[i][j]含义,从0-i的coins中,任选一个或多个,装满容量为j的背包(注意是装满)
  2. 确定递推公式:
    1. 注意这里求的是“最大组合数”,而不是“最大价值”,所以是加法(情况一+二)
    2. 情况一,不放coins[i],就是dp[i-1][j],情况二,放coins[i],就是dp[i][j-coins[i]]
    3. 注意这里不是[i-1]了,是[i]。不是看上层的,而是看本层的,这是完全背包和01背包的关键区别
  3. 初始化
    1. 初始化第一列:都有“不选”的选择,所以是1
    2. 初始化第一行:要能取模的才能赋值1,比如最小货币是2的话,当j==3,是不能装满的
// 确定dp[i][j]含义,从0-i的coins中,任选一个或多个,装满容量为j的背包
class Solution {public int change(int amount, int[] coins) {// amount 是 bagSizeint n = coins.length;int[][] dp = new int[n][amount + 1];// 初始化第一列for (int i = 0; i < n; i++) {// 都有“不选”的选择,所以是1dp[i][0] = 1;}// 初始化第一行for (int j = coins[0]; j <= amount; j++) {// 特别注意,要能取模的才能赋值1,比如最小货币是2的话,当j==3,是不能装满的if (j % coins[0] == 0) {dp[0][j] = 1;}}// 动态规划for (int i = 1; i < n; i++) {for (int j = 1; j <= amount; j++) {// 当前硬币大于背包容量,直接等于上一层if (j < coins[i]) {dp[i][j] = dp[i - 1][j];} else {// 注意这里求的是“最大组合数”,而不是“最大价值”,所以是加法(情况一+二)// 情况一,不放coins[i],就是dp[i-1][j]// 情况二,放coins[i],就是dp[i][j-coins[i]]// 注意这里不是[i-1]了,是[i]。不是看上层的,而是看本层的,这是完全背包和01背包的关键区别dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]];}}}return dp[n - 1][amount];}
}

思路:一维dp数组

  1. dp[i][j]含义不变
  2. 递推公式:
    1. 本题 二维dp 递推公式: dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]](正上方,左方)
    2. 压缩成一维:dp[j] = dp[j] + dp[j - coins[i]]
  3. 初始化:dp[0] = 1
  4. 遍历顺序
    1. 在01背包的时候,遍历j是要倒序遍历的,因为dp[j]要依靠“正上方”和“左上方”的数据。但是完全背包,它依赖的是:“正上方”和“左方”的数据。
    2. “左方”的数据由何而来?得先遍历才有,所以是for(j)是顺序遍历

附:01背包时候的二维公式和一维公式

二维: dp[i][j] = dp[i - 1][j] + dp[i - 1][j - coins[i]](正上方+左上方)

一维:dp[j] = dp[j] + dp[j - nums[i]];

因为要依赖左上方的数据,也就是上一层的旧数据,所以只能倒序遍历。遍历右的时候能取到左的数据

// 确定dp[i][j]含义,从0-i的coins中,任选一个或多个,装满容量为j的背包
class Solution {public int change(int amount, int[] coins) {// amount 是 bagSizeint n = coins.length;int[] dp = new int[amount + 1];// 初始化dp[0] = 1;// 动态规划for (int i = 0; i < n; i++) {for (int j = coins[i]; j <= amount; j++) {dp[j] = dp[j] + dp[j - coins[i]];}}return dp[amount];}
}

377. 组合总和 Ⅳ

写在前面:这个题目很有迷惑性,说是“组合”总和,但是这个“组合”又是可以有不同序列的——其实就是“排列”数,而不是求“组合”数。一定要弄清楚这个再继续。

思路:一维dp数组

  1. dp[j]的定义:从[0-i](可重复)取任意个数,填满背包j的组合(可排列!)有多少种?
  2. 确定递归公式:dp[j] = dp[j] + dp[j - nums[i]];(和上题一样,不再详细分析)
  3. 初始化:dp[0] = 1;
  4. 遍历顺序:先遍历背包,再遍历数字!!!先遍历背包,再遍历数字!!!先遍历背包,再遍历数字!!!
// 一维dp数组
// dp[j]的定义:从[0-i](可重复)取任意个数,填满背包j的组合(可排列!)有多少种?
class Solution {public int combinationSum4(int[] nums, int target) {int n = nums.length;// bagSize 是 targetint[] dp = new int[target + 1];// 初始化dp[0] = 1;// 动态规划for (int j = 0; j <= target; j++) {for (int i = 0; i < n; i++) {if (j >= nums[i]) {dp[j] = dp[j] + dp[j - nums[i]];}}// // 遍历dp检查// for(int k=0;k<=target;k++){//     System.out.print(dp[k]+" ");// }// System.out.println(" ");}return dp[target];}
}

为什么是“先遍历背包,后遍历数字”?

先说结论:

先遍历数字,后遍历背包——是组合数。

先遍历背包,后遍历数字——是排列数。

为什么会这样呢?

公式 dp[j] += dp[j - nums[i]] 的核心逻辑是:

要计算 “填满容量 j 的方式数”,可以先放入一个 nums [i],再累加 “填满剩余容量 j-nums [i] 的方式数”

  • 当先遍历数字时,“最后一个元素” 只能是当前数字(按固定顺序),所以不会产生新顺序。
  • 当先遍历背包时,“最后一个元素” 可以是任何数字(在同一容量下尝试所有数字),所以会产生不同顺序的排列。

公式本身不关心顺序,只关心 “是否加入当前数字”,而遍历顺序决定了 “加入数字的时机和范围”,最终导致结果差异。

到这里,基本上讲清楚了。可以再把518. 零钱兑换 II按照“先遍历背包,后遍历数字”的方式写一遍,答案肯定错误。

57. 爬楼梯(卡码网)

《代码随想录》:

这其实是一个完全背包问题。

1阶,2阶,… m阶就是物品,楼顶就是背包。

每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。

问跳到楼顶有几种方法其实就是问装满背包有几种方法。

思路:

  1. 确定dp含义:dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法
  2. 确定递推公式:dp[j] += dp[j - i];
  3. 初始化:dp[0] = 1;
  4. 完全背包问题:先背包,后数字(因为要先固定背包容量,再取数字,才有不同的顺序)

要是能识别出来是完全背包问题,然后又刚好做完上一题的话,这道题其实可以直接复制过去AC。

import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();// bagSize 是 n// coins[] 是 m, [1,2,3...m]// dpint[] dp = new int[n + 1];// 初始化dp[0] = 1;// 先背包,后数字for (int j = 0; j <= n; j++) {for (int i = 1; i <= m; i++) {if (j >= i) {dp[j] += dp[j - i];}}}System.out.println(dp[n]);}
}

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

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

相关文章

Linux文件操作

Linux文件Linux下的文件类型b 块设备文件---->存储类设备&#xff08;硬盘&#xff09;c 字符设备文件--->输入输出设备d 目录文件--->文件夹- 普通文件--> xxx.c xxx.h xxx.txt xxx.jpg xxx.mp4 a.outl 软链接文件-->快捷方式s 套接字文件-->网络通信p 管道…

Linux epoll 触发模式详解:LT vs ET

两种核心触发模式 1. 水平触发 (Level-Triggered, LT) 工作方式: 当文件描述符处于就绪状态时,epoll 会持续通知 只要状态未改变,每次调用 epoll_wait 都会返回该描述符 特点: c // 内核处理逻辑 (ep_send_events_proc) if (!(epi->event.events & EPOLLET)) { /…

STM32学习笔记6-TIM-2输出比较功能

第二部分&#xff0c;定时器的输出比较功能OC&#xff08;Output Compare&#xff09;输出比较输出比较可以通过比较CNT与CCR寄存器值的关系&#xff0c;来对输出电平进行置1、置0或翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形每个高级定时器和通用定时器都拥有4…

MATLAB核心技巧:从入门到精通

一 1.数值 显示 格式 format style 设置 eg: pi format longE; or 2.清除指令 clc 清除命令行窗口 clear 清除工作区 cls 3.搜索路径设置 path(path,E:\ads\) or addpath 4.M文件 用户把要实现的命令写在一个以.m为扩展的文件中&#xff0c;然后由matlab系统进行解读…

AnyDesk远程工具免费版,v9.5.110绿色便携版,秒连远程桌面,剪贴板同步超实用

[软件名称]: AnyDesk远程工具免费版 [软件大小]: 7.5 MB [软件大小]: 夸克网盘 | 百度网盘 软件介绍 AnyDesk 让远程工作变得轻而易举。无论您身处办公室的另一端还是世界的另一侧&#xff0c;只需在设备上下载、安装并启动 AnyDesk.exe&#xff0c;即可轻松访问远程屏幕。…

AI: 给Gemini CLI配上“说明书”, 精通的GEMINI.md项目记忆

嘿&#xff0c;各位技术同好&#xff01;今天我们来聊一个能极大提升AI编程助手效率的酷炫功能——Google Gemini CLI 中的 GEMINI.md 文件。 在日常开发中&#xff0c;我们越来越依赖像 Gemini 这样的 AI 助手来帮我们写代码、调试 Bug 甚至重构项目。但大家是否遇到过这种情况…

[激光原理与应用-205]:光学器件 - LD与DFB的比较

一、相同点核心原理均基于半导体材料的受激辐射机制&#xff0c;通过电子-空穴复合产生光子。依赖谐振腔实现光反馈与放大&#xff0c;形成激光振荡。采用电泵浦方式驱动&#xff0c;电流注入激发载流子&#xff0c;实现粒子数反转。材料体系主要使用III-V族化合物半导体&#…

Cursor手机版:一半是神,一半是坑

大家好&#xff0c;我是羊仔&#xff0c;专注AI工具、智能体、编程。今天想和大家聊的这个工具&#xff0c;叫Cursor&#xff0c;可能很多朋友已经不陌生了&#xff0c;它作为一款AI原生代码编辑器&#xff0c;之前可谓是风光无两。但最近&#xff0c;它又搞了点新花样&#xf…

康养休闲旅游服务虚拟仿真实训室:筑牢技能人才培养的数字基石

随着康养休闲旅游行业数字化、网络化、智能化发展趋势的深化&#xff0c;行业对高素质技能人才的实践能力和数字素养提出了更高要求。康养休闲旅游服务虚拟仿真实训室作为对接行业需求、创新实践教学模式的重要载体&#xff0c;正成为中等职业教育康养休闲旅游服务专业人才培养…

【Python 高频 API 速学 ⑤】

一、为什么把字典和集合放同一篇&#xff1f; • 底层都是哈希表&#xff0c;API 设计高度对称。 • 日常任务无非「读-写-去重-集合运算」&#xff0c;这 5 个方法就能打穿。二、三件套 & 二板斧一览名称作用返回值原地&#xff1f;dict.get(key, default)安全读取值或 de…

el-tree方法的整理

1.点击树的文字不要收缩仅点击图标的时候收缩 expand-on-click-node&#xff1a;是否在点击节点的时候展开或者收缩节点&#xff0c; 默认值为 true&#xff0c;如果为 false&#xff0c;则只有点箭头图标的时候才会展开或者收缩节点。<el-tree:expand-on-click-node"f…

支持多网络协议的测试工具(postman被无视版)

本文介绍接口调试工具&#xff0c;尽可能覆盖支持多种网络协议。写给一直写http接口&#xff0c;突然调试其他协议接口的开发 在后端开发中&#xff0c;接口调试工具的选择取决于网络协议类型和具体需求。以下是覆盖多种协议的主流工具分类推荐&#xff0c;附关键特点和场景建议…

太阳平近点角详解:概念、计算与应用

太阳平近点角详解&#xff1a;概念、计算与应用 1. 基本定义 **太阳平近点角&#xff08;Mean Anomaly&#xff0c;M&#xff09;**是描述天体&#xff08;如地球&#xff09;在其轨道上平均运动位置的角度参数。对于太阳系中的行星或卫星而言&#xff0c;它表示假设天体以恒定…

ruoyi关闭shiro校验,任何接口可以直接访问

文章目录1.找到ShiroConfig.java文件2.上述适用于get请求&#xff0c;post请求如何关闭&#xff1f;1.找到ShiroConfig.java文件 修改代码 // 原始代码 filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession,csrfValidateFilt…

数据结构进阶 详谈红黑树

目录 1. 红⿊树的概念 红⿊树的规则 红⿊树如何确保最⻓路径不超过最短路径的2倍的&#xff1f; 红⿊树的效率&#xff1a; 2. 红⿊树的实现 红⿊树的结构 红⿊树的插⼊ 红⿊树树插⼊⼀个值的⼤概过程 情况1&#xff1a;变⾊ 情况2&#xff1a;单旋变⾊ 情况3&#…

【MySQL】MySQL去重查询详解

前言 在日常的数据库操作中&#xff0c;数据去重是一个非常常见的需求。无论是查询结果去重、数据清洗&#xff0c;还是统计分析&#xff0c;我们都需要掌握MySQL中的各种去重技术。本文将详细介绍MySQL中常用的去重关键字和操作方法&#xff0c;结合实际业务场景&#xff0c;帮…

Pinterest视觉营销自动化:亚矩阵云手机实例与多分辨率适配技术

Pinterest月活突破4.5亿的视觉经济时代&#xff0c;多分辨率适配与跨设备一致性成为品牌触达用户的核心挑战。传统营销因素材模糊、设备参数固化&#xff08;如固定分辨率1080P&#xff09;、行为机械化&#xff08;如定时批量上传&#xff09;&#xff0c;导致点击率低于行业均…

01数据结构-图的邻接矩阵和遍历

01数据结构-图的邻接矩阵和遍历1.图的遍历1.1深度优先遍历1.2广度优先搜索2.邻接矩阵的代码实现1.图的遍历 1.1深度优先遍历 深度优先搜索的过程类似于树的先序遍历&#xff0c;首先从例子中体会深度优先搜索&#xff0c;例如下图1是个无向图&#xff0c;采用深度优先算法遍历…

OpenAI发布的GPT-5 更新了哪些内容,它的核心能力有哪些?AI编码能力这么强,前端程序员何去何从?

目录**1. GPT-5的核心能力与技术突破****1.1 智能水平的质变****1.2 代码生成与优化****1.3 上下文处理与长文本能力****1.4 安全与可靠性改进****2. GPT-5的应用场景与案例****2.1 医疗领域****2.2 教育与学习****2.3 企业级应用****2.4 软件开发****3. 技术细节与创新****3.1…

【无标题】AI 赋能日常效率:实用案例与操作心得分享

大语言模型&#xff08;LLM&#xff09;早已不再是实验室里的专属品&#xff0c;而是逐渐渗透到我们工作与生活的方方面面。从繁琐的文档处理到复杂的信息筛选&#xff0c;从学习辅助到日常规划&#xff0c;AI 正以 "微生产力" 的形式重塑我们的效率边界。本文将分享…