动态规划算法的题到底应该怎么做?思路教给你自己写

news2024/11/28 10:58:10

         本文是我通过做题和借鉴一些前人总结的套路而得出的思路和方法,刚好这次CSDN第八周的周赛上出了三道动态规划的题目,我会结合题目对我的思路进行一个输出,会从最简单的一维dp开始讲解到二维dp,希望对你有帮助,有错误希望指出,一起进步~~


目录

一.  应用动态规划的三大步骤

1.1 定义数组元素的含义

1.2 最优子结构(数组元素之间的关系式)

1.3 找到初始值 

二.  一维dp数组思路及解题

2.1 爬楼梯

2.2 最大子数组和 

三. 二维dp数组思路及解题

3.1 不同路径


一.  应用动态规划的三大步骤

        首先,我们先来说一下动态规划这个词,就是动态的去把一个则去对应用的数据进行一个合理的分。

        就是利用历史数据避免重复计算来对空间,时间复杂度进行一个更好的优化。而这些历史数据,我们一般要用一些变量来进行保存,一般我们用数组来保存,正常题目我们用一维数组二维数组保存就可以了,更为复杂的情况我们就可以选用更高维度的数组进行保存,这得视情况而定。

1.1 定义数组元素的含义

        首先上面也提到了我们会用一个数组来对历史数据进行一个保存,一般我们会用dp来进行一个命名,一维数组就是 dp[ ] 。

        这时最重要的一点是,我们要搞清楚我们所定义的这个数组中的每一个元素代表的是什么,dp[0]……dp[i] 你是否都清楚是什么?

        这个是我们做题的前提。dp[i]在每道题目都有每道题目的含义,搞懂我们才能进行下一步!!!

1.2 最优子结构(数组元素之间的关系式)

        从定义上来说,最优子结构就是问题的最优解包含子问题的最优解。就是我们可以通过子问题的最优解,推导出问题的最优解的意思。

        相信很多朋友会对定义上的最优子结构有困惑,但其实我们可以抛开这个名字来看,从我们每个动态规划所定义的数组dp来看!

        其实我们就是要找出数组元素之间的关系式,或者说他们之间有什么递进关系,动态规划是有种归纳法的感觉的,我们的dp[i]总是会由我们的 dp[i-1],dp[i-2]……dp[1] 来进行推导得出的,这就是我们上面所讲的利用历史数据来推导出我们最新的dp值,所以我们要找出我们定义的数组dp中的元素之间的关系式。

        这可以说是最关键的一步,也是最难的一步,一般只要花时间把关系式找出来了,题目也就迎刃而解了。

1.3 找到初始值 

        通过上面我们找到的数组元素之间的关系式,将公式推导最开始的时候,从dp[0]开始,求出第一种情况的公式,只要右边式子中除了我们求知的新的数组元素的值还有我们未知的元素时,我们都应该把公式继续往下推,找到那个所有元素都已知的公式,在此之前的元素你都需要判定是否可推,找出我们所需的初始值,将初始值进行一个直接的求解

        有了初始值,加上数组元素之间的关系式,我们就可以得到dp中所有的值,而dp中每个元素的含义都是由你自己所定义的, 你所需要求解的是什么,就应该定义它是什么,这样,求解出了dp,自然就求解出我们所要的解了。

        要是感觉还是迷迷糊糊的,不慌,我带你从题目中来理解! 


二.  一维dp数组思路及解题

2.1 爬楼梯

        题目是力扣中的题,可以直接点过去进行尝试!

 问题描述: 

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

1)定义数组元素的含义 

        首先,我们观察问题,问的是我们要上 n 层台阶总共有多少种方法,那我们可以定义我们的 dp[n] 为第 n 层台阶的方法数,所以 dp[ i ] 的含义就是:跳上 i 层的台阶总共有 dp[i] 中跳法。

 2)最优子结构(数组元素之间的关系式)

        我们知道了dp[i]的含义后,对于这道题,我们可以知道每次只能爬 1 或 2 个台阶,所以在第n层,只有两种到达的方法,一种是从 n-1 层爬 1 个台阶上来,另一种就是从 n-2 层爬 2 个台阶,我们要求的是所有可能的爬法,所以我们可以得出,dp[n] = dp[n-1] + dp[n-2]。

 3)找到初始值 

        首先观察得到的数组元素关系式,dp[n] = dp[n-1] + dp[n-2],我们知道数组的元素下标是不可以为负,最小从0开始的,所以第一个 dp[n-2] 就应该为 dp[0] 。

  • dp[2] = dp[1] + dp[0] ,其中dp[1]、dp[0]都不是已得出的值,所以初始值中应该有dp[1]、dp[0],我们必须直接求出它们的数值,可以轻易得出dp[1] = 1,dp[0] = 0 (第 0 层是出发点肯定为 0 ,第 1 层只能上一步所以只有 1 种),此时应该回顾下dp[2]是否有可能通过题目条件直接得到,可以发现可以直接上两步到第 2 层,所以最后 dp[2] = dp[1] + dp[0] +dp[2]的初始值 = 2;
  • dp[3] = dp[2] + dp[1],这次我们可以知道右边式子中 dp[1] 已经求出,dp[2]也已经推出了,所以右边式子是全部已知了,再检查下 dp[3] 是否可以通过题目条件直接得出,发现不可以,所以写代码时我们只需要把dp[1]、dp[0]、dp[2]作为初始值即可。

        这题的初始值感觉和CCF-CSP真题《202203-1—未初始化警告》有点相像的,有兴趣的朋友可以去做一下这题。

 4)代码实战

        三个步骤都出来了,直接上代码进行实战一下,我采用的是python语言的自己输出输出的方法,方便想进行尝试的朋友进行测试调试:

# 输入一个n表示要上n层台阶(n我默认大于1了)
n = int(input())
# 创建出一个数组来保存历史数据
dp = [0]*(n+1)
# 将我们所需的初始值进行求值赋值
dp[0] = 0
dp[1] = 1
dp[2] = 2
# 通过关系型求出整个dp[n]
for i in range(3,n+1):
    dp[i] = dp[i-1] + dp[i-2]
# 输出我们所求的上到第n层的方法数,即dp[n]
print(dp[n])

        这道题其实严谨来讲应该进行判断 n 的值,因为要是为1的话,初始值就不用到2了,但我们讲的是思路,就不吹毛求疵了。

2.2 最大子数组和 

        题目是力扣中的题,可以直接点过去进行尝试!

 问题描述:

        给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

        子数组 是数组中的一个连续部分。

 1)定义数组元素的含义

        首先,读题目过后我们知道要找出最大和的连续子数组,那我们可以想到在每个位置上都存入当前的最大和,最后就可以得到所有位置的最大和了。所以 dp[ i ] 的含义就是:在 i 位置时数组所能达到的最大和。

 2)最优子结构(数组元素之间的关系式)

        我们知道了 dp[i] 的含义后,对于这道题,我们要想的是每个位置应该怎么得到它的数组最大和。由于每个位置都是自己及之前的最大和,所有我们只要将 nums[ i ] 和 nums[ i ] + dp[i-1] 进行一个最大值比较就可以求出当前最大和了。

        即 dp[ i ] = max( nums[ i ] , nums[ i ] + dp[ i-1 ])

 3)找到初始值

        观察关系式,我们可以发现原数组的 nums[ i ] 就是我们所需的初始值,我们不用额外的去设置求出初始值。

 4)代码实战

def maxSubArray(self, nums: List[int]) -> int:
    # 设置一个初始的dp数组进行每个位置的最大和的存储
    dp = [0]*len(nums)
    # 遍历数组nums,通过数组关系式求出每个dp[i]的值
    for i in range(len(nums)):
        dp[i] = max(nums[i],dp[i-1]+nums[i])
    # 返回的dp数组中的最大值就是具有最大和的连续子数组的和
    return max(dp)

三. 二维dp数组思路及解题

3.1 不同路径

      老规矩,题目是力扣中的题,可以直接点过去进行尝试!

 问题描述:

        一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

        问总共有多少条不同的路径?以下图为例进行解析:

 1)定义数组元素的含义

        首先,这道题是要求从左上角到右下角有多少条路径,所以很明显数组 dp[i] [j] 的含义为:当机器人从左上角走到(i, j) 这个位置时,一共有 dp[i] [j] 种路径。那么,dp[m-1] [n-1] 就是我们要的答案了。

注意:这个网格相当于一个二维数组,数组是从下标为 0 开始算起的,所以 右下角的位置是 (m-1, n - 1),所以 dp[m-1] [n-1] 就是我们要找的答案。

 2)最优子结构(数组元素之间的关系式)

        想象一下,我们在每个格子的来处只能是 左边一格向右走一步 或者是 上面一格向下走一步 ,所以每个格子的数组元素的关系式为: dp[i] [j] = dp[i-1] [j] + dp[i] [j-1]。

 3)找到初始值

        显然,当 dp[i] [j] 中,如果 i 或者 j 有一个为 0,那么还能使用关系式吗?答是不能的,因为这个时候把 i - 1 或者 j - 1,就变成负数了,数组就会出问题了,所以我们的初始值是计算出所有的 dp[0] [0….n-1] 和所有的 dp[0….m-1] [0]。这个还是非常容易计算的,相当于计算机图中的最上面一行和左边一列。因此初始值如下:

  • dp[0] [0….n-1] = 1; // 相当于最上面一行,机器人只能一直往左走
  • dp[0…m-1] [0] = 1; // 相当于最左面一列,机器人只能一直往下走

 4)代码实战

def uniquePaths(self, m: int, n: int) -> int:
    # 假如只有一行或者只有一列时
    if m<=0 or n<=0:
        return 1
    # 设置一个dp数组存储每个位置的最多路径
    dp = [[0]*n for _ in range(m)]
    # 初始化第 0 行的路径为1
    for i in range(m):
        dp[i][0] = 1
    # 初始化第 0 列的路径为1
    for i in range(n):
        dp[0][i] = 1
    # 通过关系型动态规划每个位置的最多路径
    for i in range(1,m):
        for j in range(1,n):
            dp[i][j] = dp[i-1][j]+dp[i][j-1]
    # 输出右下角的最多路径
    return dp[m-1][n-1]

先写到这了,未完待续~~ 

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

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

相关文章

MySQL数据库基础知识

今天是更新数据库的第一篇&#xff0c;关于数据库环境搭建问题博主先不在这里介绍了&#xff0c;博主今天是直接讲知识了&#xff0c;等以后的博客&#xff0c;博主再更新数据库搭建问题。在这里我们使用命令行式客户端&#xff0c;先不使用windows下的图形化界面&#xff0c;使…

ReadingTime-十一月

CV文章浅读_not_everday0x1105.CAViT for video object re-id 2022_中科院这个月主要是要学习pytorch和一些CV baseline的复现&#xff0c;搞搞毕设雏形&#x1f199; 以后还是把笔记写纸上要么写博客&#xff0c;不放本地了&#x1f628; 网页版小绿鲸zen好用 &#x1f603; …

峰会实录 | 基于StarRocks和腾讯云EMR构建云上Lakehouse

作者&#xff1a;腾讯云EMR业务负责人陈龙&#xff08;本文为作者在 StarRocks Summit Asia 2022 上的分享&#xff09; 我目前负责腾讯云EMR 的研发工作&#xff0c;此前先后在百度、支付宝做后端研发。2011年加入腾讯&#xff0c;先后参与了腾讯云Redis、腾讯云云数据库、Ap…

小米 Civi 2 (ziyi) 机型解锁bl 获取root权限教程 +其他机型参数对比+救砖

*********机型优点与其他机型参数对比***************** 小米 Civi 2 (ziyi) 国行版机型前置由3200万主摄3200万超广角组成的双摄是它最大的亮点&#xff0c;配有4颗柔光灯。自拍相当不错。他的后置主摄采用5000万像素相机&#xff0c;IMX766传感器&#xff0c;1/1.56英寸感光…

【MybatisPlus】CRUD操作,映射匹配兼容性,ID生成策略,逻辑删除,乐观锁

文章目录MybatisPlus简介一、数据层基本的开发1. 引入jar包2. 配置数据源3. 编写实体类4. 创建Dao接口5. 测试二、CRUD使用1. 查询2. 添加3. 删除4. 修改5. 分页查询三、条件查询1. 条件查询的方式2. 多条件查询四、映射匹配兼容性1. 表字段与编码属性设计不同步2. 编码中添加了…

矩阵理论复习(二)

内积空间的定义 模与内积 向量x和y的夹角 正交向量、正交组和正交矩阵 度量矩阵 基向量内积、度量矩阵、任意向量内积之间的关系 欧式空间的两个基对应的度量矩阵彼此合同 度量矩阵的行列式的几何问题 正交补子空间 内积空间子空间U与U的正交补子空间的直和 …

LeetCode 138. 复制带随机指针的链表

难度 中等 题目链接 示例&#xff1a; 解题思路&#xff1a; 首先&#xff0c;大家肯定会这样想&#xff1a;定义一个cur循环遍历&#xff0c;每次遍历一个&#xff0c;就malloc一个。 当遍历后面的时候&#xff0c;就开始尾插。 但现在有一个问题是&#xff1a;这个random指…

通信直放站基础知识

直放站的定义 直放站&#xff08;中继器&#xff09;属于同频放大设备&#xff0c;是指在无线通信传输过程中起到信号增强的一种无线电发射中转设备。直放站的基本功能就是一个射频信号功率增强器。直放站在下行链路中&#xff0c;由施主天线从现有的覆盖区域中拾取信号&#x…

《嵌入式 - 嵌入式大杂烩》CoreMark性能测试

1 CoreMark简介 CoreMark是由EEMBC(Embedded Microprocessor Benchmark Consortium)的Shay Gla-On于2009年提出的一项基准测试程序&#xff0c;CoreMark的主要目标是简化操作&#xff0c;并提供一套测试单核处理器核心的方法。测试标准是在配置参数的组合下单位时间内运行的Co…

【树莓派不吃灰系列】快速导航

目录1. 通用篇2. Python篇3. 编程IO篇❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-11-06 ❤️❤️ 本篇更新记录 2022-11-06 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言 &#x1f4dd;&…

Slave_IO_Running: No 的解决

原因&#xff1a; 两台主从数据库的uuid相同了&#xff08;没猜错的话&#xff0c;各位的第二台虚拟机都是克隆了第一台&#xff0c;然后就改了个ip对吧&#xff09;。 解决办法&#xff1a; 必须跟着步骤来&#xff0c;一步也不能多&#xff0c;更不能少&#xff0c;请仔细…

arcgis 生成切片并发布服务

需要准备&#xff1a; 1、需要进行切割的tif文件&#xff1b; 2、切片方案文件 需要确认&#xff1a; 1、tif文件的数据源坐标系&#xff1b; 2、现有切片方案能否满足需求&#xff1b; 3、部署的地图引擎是经纬度投影还是墨卡托投影&#xff1b; 具体操作流程&#xff1a; 1…

TCP/IP协议数据链路层

目录 一、数据链路层和网络层的关系 二、以太网 1、以太网格式 2、认识MTU 三、ARP协议 1、ARP协议的作用 2、ARP协议的工作流程 3、ARP数据报的格式 4、思考&#xff1a;浏览器中输入url后, 发生的事情&#xff08;经典面试题&#xff09; 一、数据链路层和网络层的…

通信行业的必备网站

今天突然看到一首诗感触满满&#xff1a; 官策作者陈京 生如蝼蚁&#xff0c;当有鸿鹄之志&#xff01; 命如纸薄&#xff0c;应有不屈之心&#xff01; 大丈夫生于天地间&#xff0c;岂能郁郁久居人下。 当以梦为马&#xff0c;不负韶华。 乾坤未定&#xff0c;你我皆是黑马&…

西安交大讲座-实际场景(3个)出发,用户检测方式,数据驱动的网络用户行为分析建模与异常检测

讲座搬运&#xff0c;侵删&#xff01; 目录 研究背景 研究问题 问题与挑战 网络舆情分析 政策法规知识图谱 构建利益方群体识别模型 系统 ​编辑 第二个工作-异常群体映射与定位 多源社交网络用户身份管理 不用场景的用户身份映射 多个平台关联 黑产检测 基于图模型…

基于FreeCAD的dxf转机械手代码的一种实现方法

dxf文件在2D图形中使用广泛&#xff0c;将图形文件自动转换为机械手可识别的轨迹代码是机械手全自动化中一个软件衔接节点。理想的轨迹自动化转换程序可以在电脑里面直接虚拟仿真生成机械手轨迹&#xff0c;简化现场人员机械手示教流程&#xff0c;在效率和远程支持上有着实际的…

2021 神经网络压缩 (李宏毅

首先&#xff0c;为什么需要对神经网络模型进行压缩呢&#xff1f;我们在之前的课程中介绍过很多大型的深度学习模型&#xff0c;但当我们想要将这些大模型放在算力比较小的边缘设备或者其他IoT设备里面&#xff0c;就需要对大模型进行压缩。 Lower latency&#xff1a;低时延 …

刷题笔记之八(字符串通配符+参数解析+计算日期到天数)

目录 1. dateadd(datepart&#xff0c;number&#xff0c;date)函数是在日期中添加或减去指定的时间间隔 2. DML数据库操作语言负责数据的增删查改 3. 修改表结构的关键字都是alter table 表名&#xff0c;再加修改的语句 4. between and条件查询范围前闭后闭 5. 使用索引…

目标检测(1)—— 基础知识和常用数据集

一、什么是目标检测 一张图片&#xff0c;经过网络后得到输出&#xff0c;检测出感兴趣目标的一个位置&#xff0c;比如下图的车在什么地方&#xff0c;狗在什么地方&#xff1b;还要输出相应位置的目标是什么类别的。 目标检测&#xff1a;位置&#xff0b;类别 矩形框&…

vue 的 render 函数的用法:new Vue({ render: h => h(App), }).$mount(‘#app‘)

render函数的作用 render函数是vue通过js渲染dom结构的函数createElement&#xff0c;约定可以简写为h 官方文档中是这样的&#xff0c;createElement 是 Vue.js 里面的 函数&#xff0c; 这个函数的作用就是生成一个 VNode节点&#xff0c; render 函数得到这个 VNode 节点之后…