动态规划1:基本思路
作者:互联网
妈妈再也不用担心我的动态规划
基本介绍
1.动态规划的一般形式就是求最优值,比如最长公共子序列、最大子段和、最优二叉搜索树等等。
2.一般暴力破解的题目,即通过遍历所有情况,得到其中的最优解,均可采用动态规划的方式,保存已经解决的子问题的答案,减少重复计算,进而实现剪枝的目的。
3.因重点在于状态转移方式,暂称之为状态转移方程法/递推方式法,不过这种问题要用dp命名变量(Dynamic Programming,DP),更具专业性。
4.与分治法不同的是,适合动态规划法求解的问题,经分解得到的子问题往往不是相互独立的。
动态规划的基本要素
重叠子问题性质
动态规划经分解得到的子问题往往不是相互独立,即存在重复计算,通过保存答案,减少重复计算。
即计算f(n)会和f(n-1)甚至f(n-2)……有一定关系,即存在重复的计算,这里应该又和最后子结构性质带来了一定的关联性,还是类似套娃。
最优子结构性质
当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质 。
即类似套娃,或者用最简单的示例就是f(n)的最优解,和f(n-1)的最优解 相关,这个不是绝对相关。
基本解题步骤
1.题型判断:如何断定一个问题是动态规划问题?
一般情况下,需要求最优解的问题(最短路径问题,最长公共子序列,最大字段和等等,出现 最 字你就留意),在一定条件下对排列进行计数的计数问题(丑数问题)或某些概率问题都可以考虑用动态规划来解决。
可以根据给出的题目,比划比划,发现计算后面的值,需要用到前面计算的结果,那就存在**重叠子问题性质。**大多数经典的动态规划问题还满足最优子结构性质。
2.确定状态
感觉主要是看看,用一维的表示,还是得用二维的表示;感觉就是用一维的不行,就得用二维的。
即用来标记这种情况下,对应的值的情况。DP[] 或者DP[][],其对应的值即为这种情况对应的最优解。
至于状态,用来标识当前的参数,进而标识一个个的子问题。
如斐波那契数中,0 , 1, …, n 就可以视为参数,而通过这些参数定义出的 DP[0],DP[1],DP[2],…,DP[n] 就是状态,而状态与状态之间的转移方程就是 DP(n) = DP(n-1) + DP(n-2) 。
经典的背包问题(Knapsack problem)中,状态通过 index 和 weight 两个参数来定义,即 DP[index][weight] 。DP[index][weight] 则表示当前从 0 到 index 的物品装入背包中可以获得的最大重量。
3.构造状态转移方程
即确定下一个的解和之前的解的关系。
根据题目给定的条件,枚举若干子状态,然后尝试用这些子状态构造出未知状态的解,就可以轻松得到状态转移方程,当然这一步离不开大量的练习
第四步:为状态添加备忘录或者 DP Table
这个可以说是动态规划最简单的部分,我们仅需要存储子状态的解,以便下次使用子状态时直接查表从内存中获得。
备忘录 vs DP Table
备忘录方法是自顶向下对问题求解,与直接递归方法的控制结构相同,而动态规划方法是自底向上对问题求解,与迭代实现方式的结构一致。
DP Table 法(自底向上的动态规划)
顾名思义,自底向上就是从底部(递归的出口,动态规划中称为 base case)开始,不断向上回溯,计算出问题的解。下面看一下 DP Table 的状态转移过程。
设 DP 问题的基态(Base State)为 dp[0] ,目标状态为 dp[n] 。
如果我们从基态 dp[0] 开始转移,在遵循状态转移方程的情况下到达目标状态 dp[n] ,则将其称为 “自底向上” 的方法。(dp[0] → dp[n])
即从小问题,开始慢慢计算,最后得到N的解,这种容易理解。
备忘录法(自顶向下的方法)
从状态 dp[n] 开始,经状态转移向下寻找所需要的子状态的值,直到找到所有与状态 dp[n] 相关的子状态,并返回 dp[n] ,这就是自顶向下的备忘录方法。
当考虑二维数组的情况下,就像最小成本路径问题一样,此时的内存将不是按照顺序存储。
两者比较
状态:DP Table 状态转移关系较难确定,备忘录状态转移关系较易确定。你可以理解为自顶向下推导较为容易,自底向上推导较难。比如 DP[n] = DP[n - 1] + DP[n - 3] + DP[n-5] 的确定。
代码:当约束条件较多的情况下,DP Table 较为复杂;备忘录代码相对容易实现和简单,仅需对递归代码进行改造。
效率:动态规划(DP Table)较快,我们可以直接从表中获取子状态的解;备忘录由于大量的递归调用和返回状态操作,速度较慢。
子问题的解:当所有的子问题的解都至少要被解一遍,自底向上的动态规划算法通常比自顶向下的备忘录方法快常数量级;当求解的问题的子问题空间中的部分子问题不需要计算,仅需求解部分子问题就可以解决原问题,此时备忘录方法要优于动态规划,因为备忘录自顶向下仅存储与原问题求解相关的子问题的解。
表空间:DP Table 依次填充所有子状态的解;而备忘录不必填充所有子问题的解,而是按需填充。
参考:
1.算法图解-第9章 动态规划(提供了一个形象的由浅入深的认知)
2.动态规划之武林秘籍 https://mp.weixin.qq.com/s/CXLM0KC3eYYl6u2NsCpW4g
(真正让我形成了一定的策略,建议看原文)
3.力扣 题目来源+练习验证
标签:状态,问题,dp,基本思路,动态,规划,DP 来源: https://blog.csdn.net/yks0527/article/details/118658796