【知识点8】动态规划总结⭐⭐⭐⭐⭐

今天也是为了cc,努力奋斗的一天ヾ(≧▽≦*)o

前面几节介绍了动态规划的相关概念,并求解了一些经典的动态规划模型。但是在实际碰到新的问题时,初学者总是容易陷入头脑一片空白、完全无法设计状态的情况,这是正常现象,因为动态规划本身就需要经验的积累和大量做题才能有较大的提升。不过从上面的经典模型中还是能总结出一些规律性的东西,由于动态规划的重点在于状态上,所以这些规律也是用于状态的定义上的。

动态规划模型回顾

先把前面介绍过的动态规划模型列举如下:
(1)最大连续子序列和
dp[i]:以A[i]作为结尾的连续序列的最大和。
(2)最长不下降子序列(LIS)
dp[i]:以A[i]作为结尾的最长不下降序列长度。
(3)最长公共子序列(LCS)
dp[i][j]:字符串A的i号位和字符串B的j号位之前的LCS长度
(4)最长回文子串
dp[i][j]S[i]S[j]所表示的子串是否为回文子串
(5)数塔DP
dp[i][j]:从第i行第j个数字出发的到达最底层的所有路径上所能得到的最大和。
(6)DAG最长路
dp[i]:从i号顶点出发能获得的最长路径长度
(7)01背包
dp[i][v]:前i件物品装入容量为v的背包中能获得的最大价值。
(8)完全背包
dp[i][v]:前i件物品装入容量为v的背包中能获得的最大价值。

规律一

先看(1)~(4),这4个都是关于序列字符串的问题(特别说明:一般来说,“子序列”可以不连续,“子串”必须连续)。可以注意到:

  • (1)(2)设计状态的方法都是“dp[i]表示以A[i]为结尾的XXX”,其中XXX即为原问题的描述,然后分析A[i]的情况来进行状态转移;
  • (3)(4)由于原问题本身就有二维性质,因此使用了“dp[i][j]表示i号位和j号位之间XXX”的状态设计方式,其中XXX为原问题的描述(最长回文子串中的状态和原问题有关;当然,最长回文子串的状态也可以设计成“令dp[i][j]表示S[i]S[j]的区间的最长回文子串长度”,并且可解)。

这就给我们一些启发:

当题目与序列或字符串(即为A)有关时,可以考虑把状态设计成下面两种形式,然后根据端点特点去考虑状态转移方程。
(1)令dp[i]表示以A[i]结尾(或开头)的XXX。
(2)令dp[i][j]表示A[i]至A[j]区间的XXX。
其中XXX均为原问题的描述。

规律二

接着来看(5)~(8),可以发现它们的状态设计都包含了某种“方向”的意思。如:

  • 数塔DP中设计为从点(i,j)出发到达最底层的最大和;
  • DAG最长路中设计为从i号顶点出发的最长路;
  • 背包问题中则设计成dp[i][v]表示前i件物品放入容量为v的背包中能获得的最大值。

这又说明了一类动态规划问题的状态设计方法:
分析题目中的状态需要几维来表示,然后对其中的每一维采取下面的某一个表述:

  1. 恰好为i。
  2. 前i。(背包问题中用到)

在每一维的含义设置完毕之后,dp数组的含义就可以设置成“令dp数组表示恰好为i(或前i)、恰好为j(或前j)…的XXX”,其中XXX为原问题的描述。接下来就可以通过端点的特点去考虑状态转移方程。

常见的维度

我们说动态规划要设计状态数组,那么状态数组的维度通常有哪些东西呢?如下:

  1. 一个已有数组变量的数组下标范围(如LIS,LCS等等);
  2. 一个已有变量的取值范围(如背包问题中的v)

动态规划与DAG的关系

最后需要说明的是,在大多数的情况下,都可以把动态规划可解的问题看作一个有向无环图(DAG),图中的结点就是状态,边就是状态转移方向,求解问题的顺序就是按照DAG的拓扑序列进行求解的。 从这个角度可以辅助理解动态规划,建议读者能结合讲解过的几个动态规划模型予以理解。

其实,我们知道动态规划可以使用递归来实现,VisuAlgo网站提供了常见动态规划问题的可视化递归实现,在可视化中,我们可以清楚看到动态规划可解的问题可看作一个有向无环图(DAG),即递归树的形式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值