动态规划 之 背包问题
文章目录
- 0-1背包问题
- 2915.和为目标值的最长子序列的长度
- 494.目标和
- 完全背包问题
- 322.零钱兑换
- 518.零钱兑换II
- 多重背包
- 2585.获得分数的方法数
- 分组背包
- 1155.掷骰子等于目标和的方法数
背包问题是动态规划一个很重要的一类题目,主要分为0-1背包问题以及完全背包问题
基础的知识请看另一个博客
动态规划之背包问题
- 通俗来说,可以这么理解,
0-1背包问题,用于求解选择问题,结果存在一个target的限制- 传统的0-1背包问题,
<=target下的最大价值数 - 非连续子数列的
=target的最长长度
- 传统的0-1背包问题,
- 两层循环,外层循环是我们的
nums[i],也就是可选的商品,内层循环是target也就是对于空间的遍历
属于的是组合问题,要区别于排列问题,要是排列问题,外层循环是空间,内层循环是nums商品
对于这个排列还是组合的问题,请看我的另一博客
动态规划 之 排列与组合问题
- 0-1背包和完全背包的问题,总的来说递推公式十分相似,区别在于递推公式
- 0-1背包问题是 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w [ i ] ] + v [ i ] ) dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]) dp[i][j]=max(dp[i−1][j],dp[i−1][j−w[i]]+v[i])
- 完全背包问题是 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − w [ i ] ] + v [ i ] ) dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]] + v[i]) dp[i][j]=max(dp[i−1][j],dp[i][j−w[i]]+v[i])
- 如何理解?
- 答:在0-1背包问题中,对于选与不选当前的元素
nums[i],我们都只需考虑前i-1个物品的情况,所以是max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);但是对于完全背包问题的时候,不选当前的nums[i],我们就是只需考虑前i-1个物品,否则就是得考虑前i个物品的情况,所以是max(dp[i-1][j], dp[i][j-w[i]] + v[i])
0-1背包问题
2915.和为目标值的最长子序列的长度
2915.和为目标值的最长子序列的长度

思路分析:由于子序列是运行非连续的,并且又是求解的是值为target的最长长度,我们就可以思考,如何缩小化我们的问题?定义dp[i][j]表示前i种商品中,值为j的最长的长度,那么一个dp[i][j]就可以由前面的dp[i-1][j]和dp[i-1][j-nums[i]]+1的较大值转移而来
class Solution:def lengthOfLongestSubsequence(self, nums: List[int], target: int) -> int:# dp[i][j] 定义为 前i种物品中,价值为j的方案数# 0-1 背包问题 的递推公式 当 j >= nums[i] 的时候, m = len(nums)# 典型的一个0-1背包问题# 定义dp[i][j] 表示前i个物品中,和为j的最大长度# 赋值为负无穷表示无法找到,不能全部都赋值为0dp = [[-inf]*(target+1) for _ in range(m+1)]# 分为选与不选的问题,dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]] # 这个赋值很重要dp[0][0] = 0for i in range(m):for j in range(target+1):# 当无法更新的时候,dp的值就是前i-1的时候相同if j < nums[i]:dp[i+1][j] = dp[i][j]else:# 原本的递推公式 dp[i][j] = max(dp[i-1][j],dp[i-1][j-nums[i]]+1)dp[i+1][j] = max(dp[i][j], dp[i][j-nums[i]]+1)return dp[m][target] if dp[m][target] > 0 else -1
494.目标和
494.目标和

思路分析:这题明面上,要你选择要加的数和减去的数字,实际上你可以通过转化,为只用求解要加上的数字或者要减去的数字为对应转化之后的一个newtarget,然后照着2915.和为目标值的最长子序列的长度一样的思路去做,不过由于这题求解的是方案数,所以对应的递推公式以及初始值不一样
详细的分析参考灵神的分析
class Solution:def findTargetSumWays(self, nums: List[int], target: int) -> int:# 类似于0-1背包问题,求解的是运算结果等于target的表达式的数目# 我们可以照常选择正数zheng,那么对应的负数就是sum(nums) - zheng# dp[i][j] 定义为前i个数字中,值为j的数目# dp[i][j] = dp[i-1][j-nums[i]] + dp[i-1][j+nums[i]] ,计算nums[i]=0也没关系,+,-0算两个表达式# 那么dp数组怎么开这个target,原本的困惑,就是选了正数还要管这个target的范围# 由式子,选取正数的和为p,要减去的数字和为q,有p+q=s,p-q = target,就可以求解出p与q的值即可# 我们只要开的空间等于其中一个即可,也可以去一个绝对值都算上s = sum(nums) - abs(target)if s<0 or s%2 == 1:return 0m = s // 2n = len(nums)dp = [[0]*(m+1) for _ in range(n+1)]# 赋初值为1,不然后面算不了dp[0][0] = 1for i in range(n):for j in range(m+1):if j < nums[i]:dp[i+1][j] = dp[i][j]else:# dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]]dp[i+1][j] = dp[i][j] + dp[i][j-nums[i]]return dp[n][m]
完全背包问题
322.零钱兑换
322.零钱兑换

思路分析:这是一个完全背包问题,老样子,由于求解的是最小数目,所以初始值我们设置为float('inf'),然后再初始化dp[0][0]=1
class Solution:def coinChange(self, coins: List[int], amount: int) -> int:# 最少的硬币数目,硬币可以重复选,所以是完全背包问题n = len(coins)dp = [[float('inf')]*(amount+1) for _ in range(n+1)]# 定义递推公式,dp[i][j]表示前i种硬币,组成面值为j的最少硬币数目# 当j>= nums[i] 的时候,dp[i][j] = min(dp[i-1][j],dp[i][j-nums[i]])dp[0][0] = 0for i in range(n):for j in range(amount+1):if j < coins[i]:# 原本dp[i][j] = dp[i-1][j]dp[i+1][j] = dp[i][j]else:# 原本dp[i][j] = min(dp[i-1][j],dp[i][j-nums[i]]+1)dp[i+1][j] = min(dp[i][j],dp[i+1][j-coins[i]]+1)return dp[n][amount] if dp[n][amount] != float('inf') else -1
518.零钱兑换II
518.零钱兑换II

思路分析:完全背包问题,与322.零钱兑换的区别是,后者求解是最少的硬币数,而本题求解的是达到amount的方案数,两种问题带来的dp数组的初始值和dp[0][0]的值不一样
- 当求解的是类似于
322.零钱兑换的达到amount的最少硬币数,初始值为float('inf'),dp[0][0]=0 - 当求解的是类似于
518.零钱兑换II的达到amount的方案数,初始值为0,dp[0][0]=1
class Solution:def change(self, amount: int, coins: List[int]) -> int:# 区别与零钱兑换I,这个求解的是组合数n = len(coins)dp = [[0]*(amount+1) for _ in range(n+1)]dp[0][0] = 1for i in range(n):for j in range(amount+1):if j < coins[i]:# dp[i][j] = dp[i-1][j]dp[i+1][j] = dp[i][j]else:# dp[i][j] = dp[i-1][j] + dp[i][j-coins[i]]dp[i+1][j] = dp[i][j] + dp[i+1][j-coins[i]]return dp[n][amount]
- 这个
零钱兑换II是组合问题,当出现排序问题如何解决?参照下面的博客
动态规划 之 排列与组合问题
多重背包
多重背包问题:在完全背包的基础上,限制每一个物品的数量,需要判断我们的空间j到底可以容纳下几个第i个物品,就有递推公式dp[i][j] = dp[i][j]+dp[i-1][j-z*marks]
2585.获得分数的方法数
2585.获得分数的方法数

思路分析:完全背包问题和0-1背包问题的结合,但是又有新的元素的出现,递推公式有所不同
- 0-1背包问题 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i − 1 ] [ j − n u m s [ i ] ] dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i]] dp[i][j]=dp[i−1][j]+dp[i−1][j−nums[i]]
- 完全背包问题 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − n u m s [ i ] ] dp[i][j]=dp[i-1][j]+dp[i][j-nums[i]] dp[i][j]=dp[i−1][j]+dp[i][j−nums[i]]
- 多重背包问题 d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i − 1 ] [ j − n u m s [ i ] ∗ z ] dp[i][j]=dp[i][j]+dp[i-1][j-nums[i]*z] dp[i][j]=dp[i][j]+dp[i−1][j−nums[i]∗z]
- 完全背包问题的累加的情况体现在
dp[i][j-nums[i]],这个多重背包问题的累加体现在dp[i][j]
class Solution:def waysToReachTarget(self, target: int, types: List[List[int]]) -> int:# 完全背包问题,不过可以参照这个零钱兑换的思路去做,不过每次的时候要限制mod = 10**9 + 7n = len(types)dp = [[0]*(target+1) for _ in range(n+1)]dp[0][0] = 1# for i,c in enumerate(types):count,marks = c[0],c[1]for j in range(target+1):# 当不够的时候,那么就有 dp[i][j] = dp[i-1][j]dp[i+1][j] = dp[i][j]for z in range(1,count+1):if j >= z*marks:# 多重背包问题,dp[i][j] = dp[i][j] + dp[i-1][j-nums[i]*z]# 这个dp[i+1][j]最初始的值是外部的dp[i][j],我们得考虑选择z个的情况,每次都要加上之前的情况# 如果只是单纯的使用dp[i+1][j] = (dp[i][j] + dp[i][j - z * types[i][1]]) % mod# 那就是并没有正确累加先前的情况dp[i+1][j] = (dp[i+1][j] + dp[i][j - z * marks]) % modreturn dp[n][target]
分组背包
分组背包:就是有n组物品,每个物品的值都不一样,你可以选择一个物品
1155.掷骰子等于目标和的方法数
1155.掷骰子等于目标和的方法数

思路分析:
# 先放一个递归的方法
class Solution:def numRollsToTarget(self, n: int, k: int, target: int) -> int:mod = 10**9 + 7# 这个的意思是什么?一共有k种物体,k种物体加起来一共n个# 可以从递归入手,定义dfs(i,j)表示使用i个骰子,丢出j的点数# 当然,这个dfs(i,j) 可以由 dfs(i-1,j-1) + dfs(i-1,j-2)···+dfs(i-1,j-k)一起加起来# 递归返回的时候使用的是 i <=0 , j< i@cachedef dfs(i,j):# 得到结果,及时返回1if i == 0 and j == 0:return 1# i 不能<=0 ,同时要组合的结果j不能小于i,因为剩余i个骰子,最少也得是i(全部为1)if i <= 0 or j<i:return 0ans = 0# 枚举for z in range(1,k+1):ans += dfs(i-1,j-z)return ans % modreturn dfs(n,target)
动态规划
灵神分析
class Solution:def numRollsToTarget(self, n: int, k: int, target: int) -> int:mod = 10**9 + 7 # 1:1 翻译为 动态规划,dp[i][j] 表示投掷出i个骰子,组合为点数j的方案数if not (n <= target <= n * k):return 0 # 无法组成 targetdp = [[0]*(target+1) for _ in range(n+1)]dp[0][0] = 1for i in range(n):# 遍历可以找得到的空间for j in range(target+1):for z in range(1,min(k+1,j+1)):dp[i+1][j] = (dp[i+1][j] + dp[i][j-z])%modreturn dp[n][-1]相关文章:
动态规划 之 背包问题
文章目录 0-1背包问题2915.和为目标值的最长子序列的长度494.目标和 完全背包问题322.零钱兑换518.零钱兑换II 多重背包2585.获得分数的方法数 分组背包1155.掷骰子等于目标和的方法数 背包问题是动态规划一个很重要的一类题目,主要分为0-1背包问题以及完全背包问题…...
【Azure 架构师学习笔记】- Azure Databricks (11) -- UC搭建
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (10) – UC 使用 前言 由于ADB 的更新速度很快,在几个月之后重新搭建ADB 时发现UC 已经更新了很多,为了后续做ADB 的功…...
RTMP(Real-Time Messaging Protocol)
RTMP(Real-Time Messaging Protocol)是一种用于实时音视频和数据传输的协议,常见于直播和流媒体应用。 一 RTSP 协商消息 一、消息类型(Message Types) RTMP消息分为多种类型,通过Message Type ID标识&a…...
docker容器部署jar应用导入文件时候报缺少字体错误解决
如题,在导入文件时候报错如下: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager 经查是缺少对应字体,解决办法有两张: 第一种:…...
贪吃蛇解析
目录 文章结尾有代码可自取 Win32API 光标的隐藏 获取按键信息 控制光标位置 游戏开始前的准备 游戏准备及介绍 加载和欢迎界面 打印游戏指南 运行游戏 打印墙体和说明 设置蛇的各个信息 初始化及打印蛇 创造食物 运行游戏 1)打印得分情况 2&#…...
vue非组件的初学笔记
1.创建Vue实例,初始化渲染的核心 准备容器引包创建Vue实例new Vue() el用来指定控制的盒子data提供数据 2.插值表达式 作用利用表达式插值,将数据渲染到页面中 格式{{表达式}} 注意点 表达式的数据要在data中存在表达式是可计算结果的语句插值表达式…...
LeetCode 热题 100_单词搜索(60_79_中等_C++)(深度优先搜索(回溯))(初始化二维vector的大小)
LeetCode 热题 100_单词搜索(60_79) 题目描述:输入输出样例:题解:解题思路:思路一(深度优先搜索(回溯)): 代码实现代码实现(思路一&am…...
js闭包,跨域
js闭包,跨域 闭包 想象一下,你家有个大仓库(函数),仓库里放着各种东西(变量)。一般情况下,你从仓库外面是看不到也拿不到仓库里的东西的。但是,闭包就像是你在仓库里留…...
算法练习(力扣-BFS)——102. 二叉树的层序遍历
题目描述(简要概括) 题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode) 题目要求对给定的二叉树进行层序遍历(从上到下,从左到右),并返回遍历的结果。层序遍历是一种基…...
Jetson Agx Orin平台preferred_stride调试记录--1924x720图像异常
1.问题描述 硬件: AGX Orin 在Jetpack 5.0.1和Jetpack 5.0.2上测试验证 图像分辨率在1920x720和1024x1920下图像采集正常 但是当采集图像分辨率为1924x720视频时,图像输出异常 像素格式:yuv_uyvy16 gstreamer命令如下 gst-launch-1.0 v4l2src device=/dev/video0 ! …...
nlp|微调大语言模型初探索(2),训练自己的聊天机器人
前言 上篇文章记录了具体的微调语言大模型步骤,以及在微调过程中可能遇见的各种报错,美中不足的是只是基于开源数据集的微调,今天来记录一下怎么基于自己的数据集去微调大语言模型,训练自己的智能机器人!!&…...
win11安装wsl报错:无法解析服务器的名称或地址(启用wsl2)
1. 启用wsl报错如下 # 查看可安装的 wsl --install wsl --list --online此原因是因为没有开启DNS的原因,所以需要我们手动开启DNS。 2. 按照如下配置即可 Google的DNS(8.8.8.8和8.8.4.4) 全国通用DNS地址 (114.114.114.114) 3. 运行以下命令来重启 WSL…...
Gentleman:优雅的Go语言HTTP客户端工具包
gentlemen介绍,特点等 插件驱动架构:Gentleman的核心特点是其插件系统,允许用户注册和重用各种自定义插件,如重试策略或动态服务器发现,以增强HTTP客户端的功能。 中间件层:项目内置了一个上下文感知的层次…...
解锁豆瓣高清海报(三)从深度爬虫到URL构造,实现极速下载
脚本地址: 项目地址: Gazer PosterBandit_v2.py 前瞻 之前的 PosterBandit.py 是按照深度爬虫的思路一步步进入海报界面来爬取, 是个值得学习的思路, 但缺点是它爬取慢, 仍然容易碰到豆瓣的 418 错误, 本文也会指出彻底解决旧版 418 错误的方法并提高爬取速度. 现在我将介绍…...
IDEA单元测试插件 SquareTest 延长试用期权限
SquareTest是一款强大的IDEA单元测试生成插件工具,具体使用方法就不过多介绍了,这里主要介绍变更试用期,方便大家使用 配置信息 我的电脑安装前提配置条件 IntelliJ IDEA 2023.2windows 系统 软件安装 IntelliJ IDEA 直接安装插件Squar…...
PLC的五个学习步骤
五个学习步骤详解: 1. 夯实电气基础 (第一步) 核心思想: PLC控制技术是建立在传统电气控制技术之上的,因此扎实的电气基础至关重要。学习内容: 电气元件原理: 深入理解继电器、接触器、按钮、三相异步电机等常用电气元件的工作原理。这是理解电气控制回…...
深度学习05 ResNet残差网络
目录 传统卷积神经网络存在的问题 如何解决 批量归一化BatchNormalization, BN 残差连接方式 残差结构 ResNet网络 ResNet 网络是在 2015年 由微软实验室中的何凯明等几位大神提出,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得CO…...
卷积神经网络CNN
目录 一、CNN概述 二、图像基础知识 三、卷积层 3.1 卷积的计算 3.2 Padding 3.3 Stride 3.4 多通道卷积计算 3.5 多卷积核卷积计算 3.6 特征图大小计算 3.7 Pytorch 卷积层API 四、池化层 4.1 池化计算 4.2 Stride 4.3 Padding 4.4 多通道池化计算 4.5 Pytorc…...
Android:播放Rtsp视频流的两种方式
一.SurfaceView Mediaplayer XML中添加SurfaceView: <SurfaceViewandroid:id"id/surface_view"android:layout_width"match_parent"android:layout_height"match_parent"/> Activity代码: package com.android.rtsp;impor…...
web信息泄露 ctfshow-web入门web1-web10
01做题思路 判断做题的思路是读取,写入,还是执行判断大概的类型,有登录逻辑就尝试sql注入,有下载逻辑就尝试文件读取,有源码就做源码审计 02信息泄露及利用 robots.txt 以ctfshow的web1为例,访问robots…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...
