动态规划总结

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。

动态规划是一种很重要的思想,并不是具体的某一种算法,涵盖线性dp,区间dp,背包等问题。

求解

划分原问题与子问题

动态规划嘛,所谓“规划”,就是要做出决策,但是动态规划问题并不能一步到位。需要从某些状态转移过来,所以就要从原来的问题分成更小的问题,循环往复,变成可以直接求出的问题,使用某种方法组合起来就可以得出问题的答案,这一点与递归、递推很相似,所以也可以用递归来实现。

确定状态

所谓状态,就是我们在求解过程中问题的意义,做题需要知道题目在问什么,需要求什么,动态规划的求解就是从一个状态转移到另外一个状态。

有时候状态并不是通过题目直接得出,需要定义一个可以解决问题的状态。

比如说在求最长上升子序列时,不能用到第 i 个最大的值为状态,因为不知道长度。这时候,就可以改变一下状态,变成选到第 i 个数时选定第 i 个数的最长长度为状态,就知道了长度,因为选的是第 i 个数, i 一定要是最大的才能满足最长上升子序列,也知道了最大值。

确定初始状态的值

一个总问题中,可能会有一个值是已经确定了。

还是用最长上升子序列来做例子。到第 i 个数时,最开始虽然不知道最后会选什么,但是肯定有一个是可以选的,就是直接选自己。所以可以把 1~N 初始状态的值全部设为 1 。

状态转移方程

前面说到,动态规划需要从通过组合子问题变成原问题,从而得出最优解。

组合的方法就是所谓的状态转移方程。依旧以最长上升子序列为例子。

它是以前面所有状态得出最长的,并且要符合条件,所以状态转移方程则为:

f[i]=max(f[i],f[j]+1);

i=1 to N , j=1 to i-1 , a[i]>a[j]


动态规划的特点

最优子结构

最优子结构(optimal substructure) 最优子结构是依赖特定问题和子问题的分割方式而成立的条件。各子问题具有最优解,就能求出整个问题的最优解,此时条件成立。

简单来说,就是假设问题的最优解可以被子问题组合求出来,但是所有的子问题都是一个小的总问题,如果满足最优子结构,那么这个小问题也是最优解。也就是说,原问题与子问题都是最优解。

无后效性

所谓无后效性原则,指的是这样一种性质:某阶段的状态一旦确定,则此后过程的演变不再受此前各状态及决策的影响。也就是说,“未来与过去无关”,当前的状态是此前历史的一个完整总结,此前的历史只能通过当前的状态去影响过程未来的演变。

动态规划在进行第i次选择的时候不能考虑,也考虑不到,这个选择是否与第 ix(2x<i)i-x(2≤x<i) 次做出的选择有冲突。

因为动态规划的局限性,就要给动态规划铺好路,创造出一个无后效性的状态。


动态规划的方法是差不多的,但是很多问题还是有不同的变种,它们的思想都是不一样的,下面举几种经典的问题。

背包

01背包

01背包是最基础,也是最经典的问题,实际上,很多的变种背包都是由01背包变种而成的,例如多重背包,完全背包,分组背包等。

01背包,“01”,分别代表着有或者没有,也就是选或不选。

有 N 件物品和一个容量为 V 的背包。放入第 i 件物品耗费的费用是 Ci 得到的价值是 Wi。求解将哪些物品装入背包可使价值总和最大。

这道题,它的状态则为取到第 i 个数时,费用 最多为j 的选择中价值最大的数。

所以很容易得到状态转移方程:

i=1 to N
    j=0 to V
        dp[i][j]=max(dp[i][j],dp[i-1][j-C[j]]+W[i]);

多重背包

多重背包,是01背包的升级版,就是说一共有x个物品,每个都像01背包的物品一样,有价值与花费。

所以说只要把选k个物品加入背包,就是多重背包的状态转移方程。

i=1 to N
    j=0 to V
        k=1 to x[i]
            dp[i][j]=max(dp[i][j],dp[i-1][j-C[j]*k]+W[i]*k);

但是其实还有一种方法,就是还是使用01背包的方法,重复 x[i] 次,也就是可以把枚举 k 移动到枚举 i 的后面。

二进制拆分

这是对于多重背包的一种尤为有效的优化方法。

听这个名字可能感觉很高级,其实举个例子就明白:

例子:

100件物品

怎么才能用最少的数枚举出来?

实际上可以通过组合的方式:

给出

1 2 4 8 16 32

分别对应二进制下的

1 10 100 1000 10000 100000

则可以枚举出1到63(1111111),十分的优秀,再加上一个37,就可以实现1100的枚举。

用法

众所周知,背包问题有很多变种都是从01背包转过来的。01背包的特征:有选与不选两种状态。并且能通过枚举每种状态,求得最优解。

仔细思考一下,假设把100件物品分成二进制。价值,代价(如果有)就会增加到原来的同样数量的倍数,是不是就可以拿拆分后的数做01背包呢?

显然是的。

复杂度从每类物品枚举x[i]次变成了 log(x[i])log(x[i]) 次。


完全背包

完全背包与01背包的条件一样,但是物品的数量有无限个。

对于某一件物品,可以选了再选。

状态转移方程则为:

继承:dp[i][j]=dp[i-1][j];

如果能选:dp[i][j]=max(max(dp[i][j],dp[i][j-a[i]]+b[i]),dp[i-1][j-a[i]]+b[i]);

分组背包

与01背包条件一样,但是分组背包就是说有x组物品,每组物品都仅能选一个或不选。

其实还是差不多的,因为一组里的每个物品都有冲突。所以在价值为j时候对这个组内的物品进行枚举(用k表示),就能选择到重量为j的价值最大的选择。

F[k, v] = max{F[k − 1, v],F[k − 1, v − Ci ] + Wi | item i ∈ group k}

有依赖的背包

  • 第一种:要先买 K[i] 才能买 K[j] ;对于这种问题,需要把 k 做成前缀和,然后再对前缀和部分进行分组背包,就可以保证每一种都有选到的可能,例题可到http://47.112.32.87/problem/1334去看。

  • 第二种:要先支付 x 的花费才能取某组物品;对于这个问题,需要用目前最优解对组的内部进行01背包,再加上花费,然后把取这组物品不取比较,求得新的最优解,例题可到http://47.112.32.87/problem/1333查看。

  • 第三种:要先支付 x 的花费才能取某组物品,但是只能取一个;这种情况可以把每个物品的花费都加上 x ,然后分组背包,没例题。

总结:

有依赖的背包可以说算是最复杂的背包问题,但是其本质是差不多的,一般来说,都是要从依赖下手,把依赖消除,变成其他的背包问题。

混合背包

混合背包,就是有多重背包,01背包,完全背包等的结合体,面对这样的题,就要写出不同对策:01背包就按01背包选,完全背包就按完全背包写......


最长上升(下降)子序列

基础的最长上升子序列在前文中提到过了,这里讲点复杂的。众所周知,在可以决定最长下降子序列每个数时,要选择相对权值大一点的,把他们放到前面,这样才能保证长度更大。但是有一些问题,比如说在 箱子嵌套 这道题中,有多个条件,要怎么样判断权值呢?

但是可以知道,每个箱子总是有一个最长维度。观察发现,如果箱子[i]的最大维度是在一堆箱子中的最大维度中最大的,那么将没有任何一个箱子可以装的下,因为没有任何比箱子[i]的最大维度更大。

这显然符合相对权值大一点的特征,没有箱子装的下,但是箱子[i]很明显可能可以装下其它箱子。这就避免了箱子[i]可以装下箱子[j],但是 j<i ,以至于遍历不到,从而选不到的情况。即使这个箱子实际上什么东西也装不下,但是也不会影响整个最长下降子序列的长度,因为无论箱子[i]在哪里都不可能装的下其它箱子。

区间dp

区间dp就是由一个小的区间转变为大的区间,从而得到全局的解。在 P1775 石子合并(弱化版) 这道题中,首先要知道 lk,k+1r 的最优解,才能求出更大的区间 l~r 。所以需要先求出小的区间,才可以得出大的区间的最优解。

在 区间dp 中,一般第一层枚举长度,因为这样可以保证是先求出长度小的区间再求出长度大的区间,第二层一般枚举 左端点 l 与右端点 r ,第三层枚举一个 断点k (非必须)。

比如在 P1775 中,dp[l][r] 很明显是从在 lr 范围内的两个区间内得来的,在这里枚举一个 k 的断点( lr-1 ),找两个最小花费的区间,再加上合并两个区间的花费,就是 dp[l][r] 的值了。

状态转移方程:

dp[l][r]=min { dp[l][k]+dp[k+1][r]+sum[r]-sum[l-1]};

(合并还要花费 lrai\sum_l^rai )。

其他

动态规划其实还可以结合其他算法出题。例如在 得分 中,结合了 贪心 的思想。因为在选择中需要有一个顺序,所以我们需要结合贪心的思想进行排序。

总结

动态规划是一个大类,不可能所有的问题都做过。但是一种新奇的题目不可能是凭空变出来的,所以大多数都是做过的题目的变种,可以见微知著,即使只做过动态规划的冰山一角。

本文作者:cjrqwq

本文链接:https://www.cnblogs.com/yfzqwq/p/18492848

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   cjrqwq  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
展开
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.