您的位置:首页 > 理论基础 > 数据结构算法

算法与数据结构八日谈之二——动态规划

2015-07-02 07:48 381 查看

1.背包问题

01背包问题

转移方程为f[i,j]=max(f[i−1,j−wi]+vi,f[i−1,j])

转移条件为j≥wj

这是最裸的动态规划问题之一,从这个问题可以扩展出很多新问题来

可以用滚动数组将空间复杂度优化至O(n)

完全背包问题

在01背包的基础上多出来每个物品可以选择多次的条件

转移方程为f[i,j]=max(f[i−1,j−k∗wi]+k∗vi,f[i−1,j])

转移条件为j≥k∗wj

与01背包并没有很大的区别

多重背包问题

与完全背包不同的是,物品可以多次选择但有次数限制

所以直接在完全背包的转移条件上加上即可

混合背包问题

将上述3种背包混合在一起

还是没有什么区别,只需转移时对物品分类讨论即可

条件背包问题

部分物品需要在满足其它物品的限制下才能使用

对于这种问题,记忆化搜索要比直接计算方便得多

方程其实还是没有什么变化,但在转移时要对条件进行相应的修改,同时也要考虑边界情况

2.树形动规

理论上这一节应该放在树论的部分,但在这里我们还是提一下。

因为树有很强的递归结构,我们可以考虑以同样的方式进行状态转移

对于大多数的树形动规问题,我们可以在遍历时求出其dp值

在处理完子树后将子树对当前节点的答案的贡献求出即可

3.区间动规

一般的区间动规解法大多相同:

先枚举区间的长度,然后从头到尾枚举每个区间

这样的话可以保证每个前驱状态已被算到,这两步的复杂度是O(nlgn)的

转移的时候要注意边界情况,即区间中只剩下一个元素时的处理方法

4.状压动规

在某些情况下部分元素的个数极少,这时候可以考虑指数级算法。

我们用一个二进制数表示集合中每个元素的状态,于是二进制的或就可以表示集合的并,且就表示集合的交,判断一个元素是否存在只需要判断该元素所对应的位置是否为1。然后在dp时枚举每个子集并进行状态转移,就差不多了。

5.数位动规

数位动规一般是进行一些对于数字本身的统计。对于这种问题的通用思想是一次单独考虑一种数字对答案的贡献,然后利用乘法原理来合并相同的问题。还有一些小技巧,对于一些问题可以考虑补齐一个数的前导零,这样在处理时更方便

6.动态规划的优化问题

决策单调性

对于某些动态规划问题,越靠前的状态转移的决策越好,那么就可以使用单调队列优化,单调队列可以保证存在于队列中的元素的dp值得单调性,在求当前状态的dp值时只需弹出队尾的元素直到满足转移条件。计算完后再将其插入队列中,并弹出不满足单调性的决策。

斜率优化

我们将一些状态转移方程写出来,如果i是由j转移的,那么j就比k要优,在同时满足决策单调性的情况下那么k就是不必要的状态。利用合适的方法把一种决策抽象到平面上的点,那么有可能成为决策的点会在一个凸壳上,于是在转移时在凸壳上二分查找即可。

7.更一般的动态规划问题

部分递推问题

Orz能在考场上切掉这种题的人

建立图论模型解决动态规划问题

对于某些不满足无后效性的问题,我们需要用其它的手段,建立图论模型只是其中一种,更多的情况下是乱搞。

动态规划这部分我就懒得贴代码了,随便找些题去切吧。见的多了就会做了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 动态规划