算法第四课-DP靠顿悟
文章目录
引入
我感觉我没有必要专门再去写一个引入,因为无论是通俗易懂的金矿模型还是经典的01背包问题(抑或是今天老师讲的超市买东西)都讲的很不错,看这些肯定比我这个半吊子强。
算法核心问题及步骤解析
核心
往往当我们遇见满足下列条件的问题时,就可以更好地采用动态规划来解决。
-
最优子问题
-
子问题重叠
-
边界
-
子问题独立
这四个问题基本就是整个动态规划能够运作的核心,当然,我们往往还会进行额外的备忘录和时间分析
步骤
动态规划本质上依旧使用了分治的思想,同时致力于解决冗余这一方面。
-
动态转移方程
-
递归
-
自下而上
-
构造最优解
状态转移方程
写出状态转移方程可以说是整个动态规划算法运行的核心,我们以01背包为例子
这里有一个容积为V的背包,还有一堆占用体积为vi,质量为mi的货物,想出一种装法,使得其最重从而沉死翔孙。
我们设定当前开始的货物编号为begin,最后为end,那么对于每一种货物我们无非就只有装或者不装两种选择(这样递归下去就变成了一棵完全二叉树)
如下所示
|
|
很完美(01背包不需要做备忘录)
|
|
时间复杂度是O(2^n^)吗,这点我们待会再谈
动态规划主要分为:记忆化搜索(递归+记忆函数),递推
递归由于对于重复的子问题会进行大量的重复计算,所以效率会低于递推
递推
时间复杂度是O(n^2^)
|
|
记忆化搜索
|
|
时间复杂度从O(2^n^)升格到O(n^2^)
小秘籍(转载自我也忘了是哪)
思考路线
- 动规开始
- 写出dp状态和方程
- 写出dfs函数
- 添加记忆化数组
- 爆搜开始
- dfs版爆搜
- 去除外部变量
- 添加记忆化数组
滚动数组
以斐波那契数列为例,对于求第n个数,我们往往使用递推的方式进行实现,但是我们只需要开一个大小为3的数组就够用了
|
|
这是因为我们斐波那契数列的递推公式是f[n] = f[n-1] + f[n-2] (n>2),用f[3]足以放下整个公式,空间复杂度是f[3]