动态规划的一种常见技巧

news2024/9/23 5:28:49

动态规划是运筹学的一个分支,是求解决策过程最优化的过程。
动态规划并不是一种算法,而是一种思想,或者说策略
动态规划的思想就是将大问题分解成一个一个的小问题,聚焦到每个小问题并逐个击破,小问题解决了就没有大问题了
我们以一个关于最长递增子序列问题为例,设想你有一个包含N个元素的序列,你的任务是找到最长递增子序列的长度
比如说
列表[3, 1,8,2,5],最长子序列长度为3,子序列为[1, 2, 5]
列表[5, 2, ,8, 6, 3, 6, 9, 5]最长子序列长度为4, 子序列为[2, 3, 6,9]

需要说明的一个重点是,为了简化,我们目前将专注于寻找序列的长度,而不是序列本身

所以

解决动态规划问题的第一步是寻找一种可视化示例的方式,可视化是发现问题中与解决方案相关的连接和基础模式的有效方法,在解决这个具体问题时,我们显然会遇到一些关于有效序列的约束,因此,找到一种展示有效序列的方式是非常有益的。
在动态规划中,一个常见的模型是有向无环图,设想序列中的每个元素都是图中的一个节点,如果右侧的节点具有更大的值,我们就在两个节点之间建立一个有向边,下面是这个特定输入序列的有向无环图表示,这种表示法的一个优势是,在图中递增子序列仅仅是另一条路径。
在这里插入图片描述
实际上,更深入的看,最长递增子序列的长度对应于此有向无环图中最长路径的长度+1,因此,我们在技术上是在计算节点。
对这个特定问题的解决方案可能会变得更加明确,而有时,这种视角的转换正是使挑战问题变得可解的关键。

解决动态规划问题的第二步是找到合适的子问题,子问题实质上是整个问题的简化版,确定子问题可能有一些难度,但让我们关注我们已知的关于这个问题的信息。

我们知道,最长递增子序列会是初始序列的一个特定子集,确定这个子集的一种方法是通过它的起始和终点。
每个递增子序列无论长度如何,都有一个起始点和终点在原始序列中。因此,我们可以通过修改这些变量中的一个,来定义一个子问题
在这里插入图片描述
事实上,解决这个问题可以通过任意方法,但我个人觉得关注子序列的终点更为直观

我们为序列定一个子问题,命名为索引k处的lis,这意味着最长递增子序列结束于索引k。例如,结束在3的lis会是从1开始,再到2的序列,长度为2,也就是
lis[3] = 2
记住,当我们讲述这个特定问题中的lis时,我们专门指的是序列的长度。既然我们已经定义了一个可能的子问题,第三步就是要探寻子问题之间的联系。在此阶段,向自己提出一些问题通常会非常有助于思考。例如,假设你想解决找到以索引4结尾的最长上升子序列的问题。为了解这个问题,需要解决哪些子问题呢?

在这里插入图片描述
OK,这样图像化的可视化很有用,因为它清晰地展示了我们需要什么样的子问题。经过索引4的一条路径必须从索引0经过,所以我们需要知道以索引0结尾的最长上升子序列的长度,这刚好是1.
另一条路径从索引1经过,我们也需要知道这个子问题的答案,其长度也是1。最终可能以索引4结尾的路径从索引3经过,而以索引3结尾的最长上升子序列的长度是2
lis[0] = 1 lis[1] = 1 lis[3] = 2

因此,最长上升子序列的长度将是1加上所有相关子问题的最大值,即3,直观上来说,这是有道理的对吗?
如果我要找出以索引4结尾的最长上升子序列,我只需要在所有最终能达到索引4的子序列的最长上升子序列之上加1,这确实很有道理
lis[4] = 1 + max{lis[0], lis[1], lis[3] } = 3

所以,一旦我们发现了子问题之间的联系,我们就需要概述这些联系,也就是第四步。
我们再来举一个例子,看看是否能找到一个类似的流程,来解决以索引5结尾的最长上升子序列
在这里插入图片描述

这里的核心思想是,我们只考虑以索引k结尾的子问题,当且仅当k小于5,且索引k处的值小于索引5处的值。
为了见证这一关系如何运作,我们从k等于0开始,由于索引0处的位置小于6,我们需要知道这一子问题的解答
我们将继续探讨所有可能的k值,k小于5,并涉及符合题目所述限制的子问题,实际上,所以5并无特殊性
lis[5] = 1 + max{lis[k] | k < 5, A[k] < A[5]}

此逻辑适用于任何n,因此,找到以索引n结尾的最长上升子序列的子问题的一般解即为 1加上所有符合k小于n且索引k处的值小于索引n处的值的k的最大值
lis[n] = 1 + max{lis[k] | k < n, A[k] < A[n]}

现在我们准备开始实现,这是最后一步,也就是第五步,实现一个动态规划方案,其实就是按照适当的顺序解决子问题,最关键的是,在解决某个特定子问题之前,所有相关的子问题都应已解决。对于这个问题,解决问题的顺序实际上相当直观。我们必须从左至右解决子问题。现在,让我们实现一个函数

def lis(A):
    L = [1] * len(A)
    for i in range(1, len(A)):
        subproblems = [L[k] for k in range(i) if A[k] < A[i]]
        L[i] = 1 + max(subproblems, default=0)
    return max(L, default=0)

我们将用一个列表来记录长度,我们可以把所有长度初始化为1,因为每个上升子序列最少包含一个元素
然后,我们会针对输入列表的从1开始的每个索引的长度,首先确定必要的子问题,接着依据我们设定的概述来更新长度
最终,我们会返回刚刚更新的长度列表中的最大长度。实现这个功能有多种方法,因此,不要过于纠结于细节

这里,我们需要记住的一点是,我们应使用一种思维过程,以正确的顺序识别并解决子问题。我们还需要解决最后一个关键问题。直至目前,我们所做的一切,都是为了寻找最长上升子序列的长度。但我们如何真正找到实际的基础序列呢?实际上,这里的关键思路非常简单。我们需要做的,仅仅是为特定的子问题追踪前一个索引。更确切的说,如果我用索引j处的最长上升子序列的值来解决以索引i结尾的最长上升子序列的子问题,那么我可以确定索引i的前一个索引是索引j
在这里插入图片描述

我们可以观察一个具体的例子,以便更加清晰的理解。在这个序列中,索引0的前一个索引可以标为-1,因为没有序列值在索引0之前。索引1的前一个索引也一样。
prev[0] = -1 prev[1] = -1
对于索引2,前一个索引可以是索引0或索引1,选择哪一个都没关系,因为他们具有相同的长度值。
prev[2] = 0
而对于索引3,前一个索引只有一个选择,即索引1
prev[3] = 1
最终,索引4只有一种选择,因为计算索引4处的长度的子问题是以索引3为终点的最长上升子序列,因此前一个索引也就是3
prev[4] = 3

这种追踪前一个子问题的模式是解决动态规划问题的一种常见技巧

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

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

相关文章

数据融合工具(7)文本属性值规范化处理

一、需求背景 数据检查方案中&#xff0c;对文本属性值的检查一般包括以下内容&#xff1a; 检查属性值中不能含有不合理的标点符号&#xff08;“&#xff0c;”、“&#xff1f;”、空格、换行符等&#xff09;&#xff1b; 确认全部属性字段是否为半角&#xff1b; 名称简…

FastAPI 学习之路(四十二)利用Docker部署发布

我们之前的部署都是基于本地的部署&#xff0c;我们这次来看下&#xff0c;如何使用docker部署我们的fastapi项目。 编写Dockerfile ①&#xff1a;首先编写一个docker镜像的制作文件Dockerfile FROM python:3.10RUN pip install fastapi uvicorn aiofiles sqlalchemy pytho…

led灯什么牌子的质量好呢?盘点五款高口碑的led灯

很多新手小白在选购护眼台灯前&#xff0c;都会思考led灯什么牌子的质量好呢&#xff1f;这因为有的无良商家因为想要降低成本&#xff0c;使用一些廉价低劣的处理器&#xff0c;led灯的电压和功率都难以保证&#xff0c;有的甚至会产生有害的辐射&#xff0c;对人体的健康造成…

基于web、dns、nfs的综合实验

题目&#xff1a; 现有主机 node01 和 node02&#xff0c;完成如下需求&#xff1a; 1、在 node01 主机上提供 DNS 和 WEB 服务 2、dns 服务提供本实验所有主机名解析 3、web服务提供 www.rhce.com 虚拟主机 4、该虚拟主机的documentroot目录在 /nfs/rhce 目录 5、该目录由 no…

win11下部署Jenkins,build c#项目

一个c#的项目&#xff0c;由于项目经理总要新版本测试&#xff0c;以前每次都是手动出包&#xff0c;现在改成jenkins自动生成&#xff0c;节省时间。 一、下载Jenkins&#xff0c; 可以通过清华镜像下载Index of /jenkins/windows-stable/ | 清华大学开源软件镜像站 | Tsingh…

低压电柜导线颜色标准

低压电柜导线颜色标准主要遵循以下规则&#xff1a;‌ 保护导线&#xff08;‌PE&#xff09;‌必须采用黄绿双色&#xff0c;‌这是为了明确标识接地线路&#xff0c;‌确保安全。‌ 动力电路的中线&#xff08;‌N&#xff09;‌和中间线&#xff08;‌M&#xff09;‌必须…

Windows 如何安装和卸载 OneDrive?具体方法总结

卸载 OneDrive 有人想问 OneDrive 可以卸载吗&#xff1f;如果你不使用当然可以卸载&#xff0c;下面是安装和卸载 OneDrive 中的卸载应用具体操作步骤&#xff1a; 卸载 OneDrive 我们可以从设置面板中的应用选项进行卸载&#xff0c;打开设置面板之后选择应用&#xff0c;然…

人工智能算法工程师(中级)课程1-Opencv视觉处理之基本操作与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程1-Opencv视觉处理之基本操作与代码详解。OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它提供了各种视觉处理函数&am…

《python程序语言设计》2018版第5章第55题利用turtle绘制平方函数,我用的是我之前的解题,有点扛不住了。兄弟们

直接上图 import turtleturtle.speed(20) turtle.penup() # 这里就是我理解的平方函数的概念&#xff0c;不知道对不对 for i in range(-18, 19):turtle.goto(i, i ** 2)turtle.pendown()turtle.hideturtle() turtle.done()只有平方函数的结果。没有横线竖线。各位兄弟们自己脑…

硅谷甄选4(项目主体)

1.路由配置 1.1路由组件的雏形 src\views\home\index.vue&#xff08;以home组件为例&#xff09; 安装插件&#xff1a; 1.2路由配置 1.2.1路由index文件 src\router\index.ts //通过vue-router插件实现模板路由配置 import { createRouter, createWebHashHistory } fro…

【Python学习笔记】调参工具Optuna + 泰坦尼克号案例

【Python学习笔记】调参工具Optuna&泰坦尼克号案例 背景前摇&#xff1a;&#xff08;省流可不看&#xff09; 最近找了份AI标注师的实习&#xff0c;但是全程都在做文本相关的活&#xff0c;本质上还是拧螺丝&#xff0c;就想着学点调参、部署什么的技能增加一些竞争力&a…

昇思MindSpore学习笔记6-02计算机视觉--ResNet50迁移学习

摘要&#xff1a; 记录MindSpore AI框架使用ResNet50迁移学习方法对ImageNet狼狗图片分类的过程、步骤。包括环境准备、下载数据集、数据集加载、构建模型、固定特征训练、训练评估和模型预测等。 一、概念 迁移学习的方法 在大数据集上训练得到预训练模型 初始化网络权重参数…

爬虫-浏览器自动化

什么是selenium selenium是浏览器自动化测试框架&#xff0c;原本用于网页测试。但到了爬虫领域&#xff0c;它又成为了爬虫的好帮手。有了 selenium&#xff0c;我们便不再需要判断网页数据加载的方式&#xff0c;只要让 selenium 自动控制浏览器&#xff0c;就像有双无形的手…

海南云亿商务咨询有限公司抖店开店正规吗?

在当今的数字经济时代&#xff0c;抖音电商已经成为一股不可忽视的力量。无论是品牌商还是个人创业者&#xff0c;都纷纷涌入这个充满活力和潜力的市场。而在这个风起云涌的浪潮中&#xff0c;海南云亿商务咨询有限公司以其专业的服务和敏锐的市场洞察力&#xff0c;成为抖音电…

GitHub 创始人资助的开源浏览器「GitHub 热点速览」

你是否注意到&#xff0c;现在主流的浏览器如 Chrome、Edge、Brave 和 Opera 都采用了谷歌的 Chromium 引擎&#xff1f;同时&#xff0c;谷歌每年不惜花费数十亿美元&#xff0c;确保其搜索引擎在 Safari 中的默认地位&#xff0c;甚至连 Firefox 也难逃商业利益的影响&#x…

一款好用的特殊字符处理工具

跟mybatis代码的时候&#xff0c;偶然发现的一款特殊字符处理工具java.lang.StringTokenizer。平常&#xff0c;我们看到的mybatis mapper.xml里面各种换行各种缩进&#xff0c;但日志文件里面的sql都是整整齐齐的。没有换行符&#xff0c;缩进等。就是利用该工具做的格式化处理…

在Ubuntu下安装samba实现和Windows系统文件共享

一、安装 apt install -y samba samba-clientSamba is not being run as an AD Domain Controller: Masking samba-ad-dc.service Please ignore the following error about deb-systemd-helper not finding those services. (samba-ad-dc.service masked) Created symlink /et…

每天一个数据分析题(四百二十七)- 方差分析

下面是一个方差分析表&#xff1a; 表中A&#xff0c;B&#xff0c;C&#xff0c;D&#xff0c;E五个单元格内的数据分别是&#xff08; &#xff09;。 A. 40&#xff0c;5&#xff0c;35&#xff0c;60&#xff0c;1.71 B. 40&#xff0c;5&#xff0c;35&#xff0c;60&a…

仙侠天花板,圆你土豪梦,上古传说手游详细图文架设教程

前言 这次给大家带来的是一款我的心头好&#xff0c;绝对是我所有架设游戏里排名前三的&#xff0c;一款经典的仙侠手游&#xff0c;安卓苹果双端&#xff0c;画质精美程度真的没有哪几个游戏可以比得上&#xff0c;故事情节加上背景音乐绝对值得沉浸其中慢慢玩&#xff0c;最…

JSONObject和Map<String, Object>的转换

一、前言 Java开发中出参返回和入参传入更灵活的方法是使用Map<String, Object>入参或出参&#xff0c;或者使用JSONObject。 1、好处&#xff0c;参数可变&#xff0c;对接口扩展性很友好。 public ResponseData<WXModelDTO> getUserInfo(RequestBody Map<…