动态规划初级

来源:互联网 发布:湖北地税软件下载 编辑:程序博客网 时间:2024/06/06 09:46

一.最长不下降子序列(LIS)
状态设计: dp[i]表示以第i个数结尾的不下降子序列的最大长度(最长不下降子序列!子问题!)
这样考虑:这个以a[i]结尾的序列,要么只包含a[i],要么加上前面的一段序列,只有这两种可能。如果只包含a[i],那么dp[i]就是1;如果加上前面的一段序列,就要加上最长的那个序列的长度,dp[i]就是max{dp[1] ~ dp[i - 1]} + 1。对于只包含a[i]的情况,我们可以在最初将dp全部初始化为1。所以我们在递推的过程中只考虑第二种情况就好了。
递推式如下:

dp[i] = max{dp[j]} + 1;//a[j] <= a[i]且j < i

简单变形:上升,不上升,下降。
二.最长公共子序列( LCS)
**状态设计:**dp[i][j]为A1……Ai,B1……Bi的公共子序列的最大长度
这样考虑:我们很自然地着眼于Ai和Bi这两个元素。二者有相等,不相等两种情况。如果二者相等,那很好,序列的长度增加了1。在谁的基础上增加了1呢?当然是在A1……A(i - 1)和B1……B(i - 1)的最长公共子序列的基础上,将Ai(或者说Bi)加上。

设序列A = {A1,A2,…,Ai}和B = {B1,B2,…,Bj}的最长公共子序列为C={C1,C2,…,Ck} ,则
(1)若Ai = Bj,则Ck = Ai = Bj,且C1,C2,…, Ck-1是A1,A2,…,Ai-1和B1,B2,…,Bj-1的最长公共子序列.
(2)若Ai ≠ Bj,且Ck ≠ Ai,则Z是A1,A2,…,Ai-1和B的最长公共子序列.
(3)若Ai ≠ Bj,且Ck ≠ Bj,则Z是A和B1,B2,…,Bj-1的最长公共子序列.

递推式如下:

if(A[i] == B[j])    dp[i][j] = dp[i - 1][j - 1] + 1;else    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

边界:

dp[i][j] = 0;//i = 0或j = 0时

注意:
最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,简称LCS)的区别为是最长公共子串的串是连续的
三.最大连续子序列和
**状态设计:**dp[i]表示第i个数及其左边连续若干个数的和的最大值
**这样考虑:**a[i]是一定要加入的,因为要保证连续。那么dp[i - 1]呢,如果它大于0,就说明对dp[i]有贡献,要加上。反之,则不加。
递推式如下:

if(dp[i - 1] > 0)    dp[i] = dp[i - 1] + a[i];else    dp[i] = a[i];

四.背包问题:
推荐阅读DD大牛的《背包九讲》。链接附上:https://www.kancloud.cn/kancloud/pack/70124
五.动态规划做题一般步骤:
第一步:找到一个原问题,并分析它的子问题
第二步:根据原问题和子问题确定状态
原问题和子问题中有几个变量一般状态就可以初步确定成几维
状态的参数一般有:
1)描述位置的:前(后)i单位,第i到第j单位,坐标为(i,j)等
2)描述数量的:取i个,不超过i个,至少i个等
3)描述对后有影响的:状态压缩等一些特殊的性质
结合子问题,敢想敢试,不要轻易否定一个状态
第三步:确定状态转移方程
六.小知识:
①先由最一般的情况入手,考虑它是如何被转移来的,再写出边界
②在多阶段决策问题中,阶段定义了天然的计算顺序
③如果状态不够清晰,可以考虑改变描述或者加一个维度
④动态规划思想的本质是在一个有向无环图(DAG,满足无后效性)中求一个函数的最优值
⑤如果DP没有思路就写一个搜索,可由记忆化搜索来得到DP递推式
⑥注意第0行(列)是初始化为0还是inf
⑦动态规划原理——加法原理、乘法原理
⑧状压DP:用0到n-1读入,比较方便
⑨无后效性:动态规划只适用于解决当前决策与过去状态无关的问题。如果当前问题的具体决策,会对解决未来的问题产生影响,就无法保证决策的最优性。
⑩最优子结构:问题的最优解包含着它的子问题的最优解

原创粉丝点击