[动态规划] 什么是动态规划
参考:
- 什么是动态规划?动态规划的意义是什么?(转自知乎)
- 什么是动态规划(Dynamic Programming)?动态规划的意义是什么? - 阮行止的回答 - 知乎 https://www.zhihu.com/question/23995189/answer/613096905
公式符号:
- $\left \lceil \right \rfloor $
本文可以顺便搞明白 “递推、贪心、搜索” 与 “动态规划”之间的关系。
动态规划是解决「某一类问题」
动态规划是对「某一类问题」的解决方法,重点在于如何鉴定 某一类问题 是动态规划可解的,而不是纠结于使用 「递归」还是 「递推」来解决。
如何鉴定这「某一类问题」示动态规划可解的呢?
答:还是要从计算机如何工作说起:计算机的本质是一个状态机,内存里存储的所有数据构成了当前的「状态」,CPU只能利用当前的状态计算出下一个状态。
当你试图使用计算机解决一个问题时,其实就是在思考如何将该问题表达成 状态(用哪些变量存储哪些数据)、以及 如何在状态中转移(怎样根据一些变量计算出另一些变量)。所以,所谓的:
- $\left \lceil{空间复杂度} \right \rfloor $:就是为了支持你的计算所必须存储的状态最多有多少个;
- $\left \lceil{时间复杂度} \right \rfloor $:就是从初始状态到达最终状态 需要走多少步;
状态 与 状态转移
比如说我想计算第100个非波那契数,每一个非波那契数就是这个问题的一个**「状态」**,由一个状态(斐波那契数A)转移到另一个状态(斐波那契数B)的过程 叫做 「状态转移」。
根据斐波那契数列的公式我们知道,每求一个新数字只需要之前的两个状态。
- 所以同一个时刻,最多只需要保存两个状态,空间复杂度就是常数;
- 每计算一个新状态所需要的时间也是常数且状态是线性递增的,所以时间复杂度也是线性的。
上面这种状态计算很直接,只需要依照固定的模式从旧状态计算出新状态就行(a[i]=a[i-1]+a[i-2]),不需要考虑是不是需要更多的状态,也不需要选择哪些旧状态来计算新状态。对于这样的解法,我们叫==递推==。(递推与递归的区别,可见:递推 | 递归 | 迭代)
阶段
非波那契那个例子过于简单,以至于让人忽视了阶段的概念,所谓**==「阶段」==是指随着问题的解决,在同一个时刻可能会得到的不同状态的集合。**
非波那契数列中,每一步会计算得到一个新数字,所以每个阶段只有一个状态。
举一个其他例子,假如把你放在一个围棋棋盘上的某一点,你每一步只能走一格,因为你可以东南西北随便走,所以你当你同样走四步可能会处于很多个不同的位置。从头开始走了几步就是第几个阶段,走了n步可能处于的位置称为一个状态,走了这n步所有可能到达的位置的集合就是这个阶段下所有可能的状态。
有了阶段之后,计算新状态可能会遇到各种奇葩的情况,针对不同的情况,就需要不同的算法,下面就分情况来说明一下:
贪心:一个阶段的最优可以由前一个阶段的最优得到
假如每个阶段有n个状态,每个阶段都有多个状态(不同阶段的状态数量不必相同)。一个阶段的一个状态可以得到下一个阶段的所有状态的几个。
所以,如果我们要计算出最终阶段的状态数 自然要经历之前每个阶段的某些状态。
如果是==「暴力算法」==:就相当于每个阶段的所有状态我们都需要经历,然后才得到最后阶段的所有状态。即 我们把所有的可能性都计算了一遍。
好消息是,有时候我们并不需要真的计算所有状态。举个例子:从棋盘的左上角到达右下角最短需要几步?
答:
某个阶段确实可以有多个状态,正如这个问题中走n步可以走到很多位置一样。但是同样n步中,有哪些位置可以让我们在第n+1步中走的最远呢?没错,正是第n步中走的最远的位置。即“下一步最优是从当前最优得到的”。
所以为了计算最终的最优值,只需要存储每一步的最优值即可,解决符合这种性质的问题的算法就叫==「贪心」==。
如果只看最优状态之间的计算过程是不是和非波那契数列的计算很像?所以计算的方法是递推。
斐波那契数列 每个阶段只有一个状态,和贪心算法每个阶段只选择最优的那一个状态类似。
既然问题都是可以划分成阶段和状态的。这样一来我们一下子解决了一大类问题:一个阶段的最优可以由前一个阶段的最优得到。
动态规划:无后效性
接着上面的例子。如果一个阶段的最优 无法用前一个阶段的最优得到呢?
例如迷宫的例子,在计算从起点到终点的最短路线时,你不能只保存当前阶段的状态,因为题目要求你最短,所以你必须知道之前走过的所有位置。因为即便当前所在的位置不变,之前所走过的路线的不同 也是会影响之后走的路线的。
此时我们就需要保存 每个阶段所经历的状态,根据这些状态才能算出下一个状态。即之前所走的路线的每一步 都会 影响到下一步的选择,这种情况叫做 有后效性。对于这种情况,我们需要使用暴力算法。
但是呢,有一类问题,看似需要之前所有的状态,其实不用。以“最长上升子序列”为例子,来说明该例子为什么不必需要暴力搜索,进而引出动态规划的思路。
求解最长上升子序列:
答:
首先,从头到尾依次枚举是否选择当前的数字,每选定一个数字就要去看看是不是满足“上升”的性质,这里第i个阶段就是去思考是否要选择第i个数,第i个阶段有两个状态,分别是选和不选。
每次当我决定要选择当前数字的时候,只需要和之前选定的一个数字比较就行了!这是和之前迷宫问题的本质不同!
所以,我们可以不需要记录之前所有的状态(这个和 迷宫问题 不同)。
既然我们的选择已经不受之前状态的组合的影响了,那时间复杂度自然也不是指数了。此时,虽然我们不在乎某序列之前都是什么元素,但我们还是需要这个序列的长度的,只需要使用一个变量来记录某个元素结尾的LIS长度即可。
因此第i个阶段的最优解只是由前i-1个阶段的最优解得到的,然后就得到了DP方程:
L I S ( i ) = m a x { L I S ( j ) + 1 } j < i a n d a [ j ] < a [ i ] LIS(i)=max\{LIS(j)+1\} \ \ \ \ j<i \ and\ a[j] < a[i] LIS(i)=max{LIS(j)+1} j<i and a[j]<a[i]
所以,动态规划是 无后效性 的。
小结:
所以一个问题是该用递推、贪心、搜索还是动态规划,完全是由这个问题本身阶段间状态的转移方式决定的!
- 每个阶段只有一个状态->「递推」;
- 每个阶段的最优状态都是由上一个阶段的最优状态得到的 -> 「贪心」;
- 每个阶段的最优状态是由之前所有阶段的状态的组合得到的->「搜索」;
- 每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到而不管之前这个状态是如何得到的->「动态规划」。
其中,
- 每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到 ====该性质 叫做 最优子结构。
- 而不管之前这个状态是如何得到的 ==== 这个性质叫做无后效性。
[动态规划] 什么是动态规划相关推荐
- 《强化学习与最优控制》学习笔记(一):确定性动态规划和随机性动态规划
写在前面的 这本书的作者是Dimitri Panteli Bertsekas教授,1942年出生于希腊雅典,美国工程院院士,麻省理工大学电子工程及计算机科学教授.Bertsekas教授因其在算法优化与 ...
- 动态规划-03-线性动态规划
一.简介 动态规划主要任务,确定状态方程(fn 和 fn-1.fn-2),和边界条件(n=1,2),联想高中递推问题. 线性动态规划的主要特点是状态的推导是按照问题规模 i 从小到大依次推过去的,较大 ...
- 【动态规划】线性动态规划
吐槽:动态规划这个东西,只要推不出状态转移方程,一切都白搭 基础知识 一. 动态规划 动态规划中最重要的三个概念:最优子结构,重复子问题,无后效性. 最优子结构:如果问题的最优解所包含的子问题的解也是 ...
- 【算法】动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )
文章目录 一.动态规划场景 二.动态规划分类 1.坐标型动态规划 2.前缀划分型动态规划 3.前缀匹配型动态规划 4.区间型动态规划 5.背包型动态规划 一.动态规划场景 动态规划 动态规划使用场景 ...
- 0-1背包问题 动态规划java_C#使用动态规划解决0-1背包问题实例分析
// 利用动态规划解决0-1背包问题 using System; using System.Collections.Generic; using System.Linq; using System.T ...
- python动态规划图解_动态规划案例之python实现(一)
假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: 2 解释: 有两 ...
- 【动态规划1】动态规划的引入(今天刷洛谷了嘛)
注: P4017 最大食物链计数 因为现在还不会拓扑排序,所以暂且放到以后去解决! P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles #include&l ...
- 动态规划java LCS_动态规划递归求解LCS长度 | 学步园
这个问题的叙述太多了,就不重复了.这里我只是球出了LCS的长度,事实上,长度还是非常有用的,如判断两个字符串相似程度.主要是想说明的是,利用递归来求解.非常方便.今天下午了试了3个题,一个回文数,一个 ...
- 钢条分割 动态规划java_【动态规划】初识,钢条切割问题
正文之前其实动态规划老早之前就看过, 但是可惜的是印象不深,到今天彻底忘得差不多了,这两天看<算法导论>终于让我啃下了二叉搜索树和红黑树两个家伙,虽然还未曾熟练于胸,但是基本能用了...现 ...
- java动态规划解法_动态规划通用解法总结(示例代码)
背景:leetcode刷题遇到动态规划的题目,做不出来时看别人的code,也可以理解,但还是没有找到create solution的技巧,单纯的comprehend and remeber,直到遇到了 ...
最新文章
- flamingo的中文意思是什么_flamingo.是什么意思
- 微信小程序web-view能发送ajax,微信小程序web-view组件的坑
- 学习Kotlin(五)函数与Lambda表达式
- python字符串类型_python字符串类型介绍
- 用户IP地址的三个属性的区别(HTTP_X_FORWARDED_FOR,HTTP_VIA,REM_addr
- 【BZOJ3289】Mato的文件管理,莫队+树状数组
- 程序员面试题 php_程序员面试必备PHP基础面试题 – 第十五天
- 基于Android的公交线路查询系统设计与实现
- 不知道免费去水印图片软件哪个好?来看看这3个软件
- 【转】MIT博士林达华解说数学体系
- 安装 truffle (CentOS7 与 Windows)
- Struts Tiles 框架概述
- P1-2017级第一次算法上机 F SkyLee的艾露猫
- Zephyr 3.2 弃用devicetree 中node 里的label property
- 国稻种芯百团计划行动 下好先手棋安徽“育繁推一体化”格局
- SD卡启动第一篇 (SD卡分区)
- google开源服务器apprtc的搭建
- 【伸手党福利】JSONObject转String保留空字段
- 删除HTML中特定标签,同时保留标签里的内容处理办法
- 学习分享:学术前言趋势分析1—论文数据统计