动态规划心得总结

1.1. 常规情况的基本步骤

1.2. 给出递推函数的定义 & 找出递推关系

基本步骤中的第一步、第二步是紧密关联的。递推函数定义的不同会导致递推关系不同,甚至决定了在这种定义下能否找出对应的递推关系。当我们确认递推函数的定义后,那么其对应的递归关系也是确定的、唯一的(如果有的话)。

因此第一步很关键,这里也有些隐藏着的经验、细活,很多博客都不会说到,这是我自己思考总结的,包括我看的算法书上也没有写,都是根据题目直接给出了对应的递推函数定义,然后去论证怎么去得到递推关系,没有讲为什么要这样定义、是怎样想到这样的定义等。

一道题可能有多种递推函数的定义,但这些递推函数的有一个共同点就是:变量数量是一定的。

那么这个维度该怎么确认呢?总体看,这是一个活的过程,但也有些规律、经验可以依据。

首先看有几个输入,判断哪些输入是作为常量,哪些输入能够作为变量、或间接的贡献出变量。比如换钱的方法数,给了两个输入,一个是能用的币值list,一个是要换的钱。我们判断这两个值都能作为变量或间接贡献出变量:对于前者,我们会想到用多少中币值来计算,对于后者我们会想先从小钱开始,一步一步换到我们给定的钱数。再比如对于机器人到达指定位置的方法数这道题,给定了四个输入:N表示位置数、M表示起始位置、K表示使用的步数、P表示目标位置。我们可以看到N和M是常量,K、P作为变量。

其次,我们在上一步确定好能贡献变量的输入后,还要再选规划的方法,来确认每个输入能贡献多少变量。其实上一步是比较确定的,哪些输入是规划过程中的常量,哪些输入是规划过程中的变量,是比较明显的,容易确认的。但是规划的方法是多变的。一般来说确定在某一个输入上有几个在规划时用到的动点:比如对一个字符串来说,一般有两种选择:使用两个动点来表示区间的两端;使用一个动点来表示区间的一端,然后区间的另一端是固定死的。一个动点就对应的递推函数定义中的一个变量。

根据上面两步我们确认递推函数的维度。但在上面第二步,动点数量依赖于规划方法的选择,而规划方法就直接对应着递推函数的逻辑定义了。选规划方法最为关键重要,细活都在这。

在这一步需要跳出既有思维的约束,就是发现每一类规划方法中,能变的地方在哪,不同变化的一种组合就是具体的一种规划方法。

比如:对于字符串,我们进行区间规划的时候,区间有两端,这时我们面对的两种选择:在规划时,只固定一端,还是两端都动?如果固定一端的话,是固定哪一段,固定左端还是右端?然后我们还要确认,F(x)表示的是以x位置字符结尾(或开头)的xxx结果,还是说在【0,x】区间内,不限定以x位置字符结尾的xxx结果?

再比如,对于机器人到达指定位置的方法数,我们是把F(x,y)定义为机器人从位置x走y步到达常量P点的方法数,还是把F(x,y)定义成机器人从常量开始位置走x步到达位置y的方法数?这两种选择其实都是可以的。

再比如,对于龙与地下城游戏中,我们是把F(x,y)定义成从常量开始位置出发到达位置(x,y)所需的最小初始血量,还是说把F(x,y)定义成从变量位置(x,y)出发到达常量终点的所需最小初始生命值?对于这道题前者是行不通的,后者才可以。这就是个固定点选择导致的可行性与否。

……

……

……

在这个过程中要多尝试,一个错误观念是,从一开始就把自己第一想的到规划方法用上了,之后把所有时间放在尝试了去找递推关系上,就算找不到还是不换规划方法,然后就一直死磕着。。。

1.3. 根据递推关系写出动态规划版本代码

1.4. 其他

上面说的是常规性的,一般性的步骤流程。但问题是多变的,需要具体分析。

比如:遇到的问题使用上面的步骤搞不定,像最大矩阵系列问题。信封嵌套问题等。
最大矩阵系列问题缺在完全放弃了直观的建模,生搬硬套常规的做法,信封嵌套问题属于要先对输入处理下,然后转为其他问题的解法。

反正动态规划都会用到辅助矩阵,辅助矩阵怎么定义、怎么用就是展现个人能力的地方,要充分发挥想象。
比如最长递增子序列一题用到了一个记录了子序列长度到其结尾最小数映射关系的辅助矩阵,这个很有特色。

Original: https://www.cnblogs.com/stepfortune/p/16245018.html
Author: 迈吉
Title: 动态规划心得总结

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/594688/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球