DP复习

重新复习了算法导论的DP一章:

以前也看过, 不过那时候就是看, 基本没怎么用,

现在回过头来再看,还是很多发现。

根据求解子问题顺序的不同, 程序也会变为递归和迭代两种, 比如 a[i, k](k == 1 || k ==2, k依赖于每一步的选择空间有几个) 的结果依赖于 a[i-1, 1] 和 a[i-1, 2]。

如果是顺序的从 i = 0 开始求, 那么就是迭代。

如果是逆序的从i= N开始求, 那么就会变为递归。

不过每一个子问题求出最优解以后, 就应该把该解记下来, 以应对重叠子问题。

(动态规划这个名字其实有点误导, 这里有个原因, DP之父Richard Bellman, 也是BF最短路径的发明者, 以前在军事单位工作, 在研究中

发现了此方法, 但其上司十分厌恶理论研究, 于是不得不改了一个和这个算法听上去无关的名字, 动态规划, 其实本来是要叫 multistage decison process的

, 这个名字显然很贴切, 哎, 码农在哪都受气)

DP = divide and conqueror + memorization.

DP的两个条件, 最优子结构 和 重叠子问题:

最优子结构, 即在求解的某一step中(DP是步进式的), 在此step的最优解必然包含了子问题的最优解(否则, 可以用代替大法,把更优解拿过来, 那么会得到一个

此step的更优解, 矛盾了, 因此必然包含子问题的最优解)

重叠子问题, 即在求解过程中, 会不止一次的遇到同样的问题, 而这时候, DP的memorization可以极大的提高效率(呵呵 就是就是cache嘛, 不过不会动态更新)

书上没有强调步进式(其实更准确的说, 应该是层(level)进式), 可能觉得这是基本前提吧, 不过在解DP时, 步进式是要贯彻始终的思想,有了步进式, 才有了分解子问题。

那书上第一道例题, 双流水线来说, 步进式就是在每一个操作工序都要依次经过, 这样最后的大问题就可以分解成 这一步, 和以前所有步组成的最优解。

而重叠子问题则提现在, 比如在求 a[i, 1] 和 a[i, 2],都要求依赖于 a[i-1, 1] 和 a[i-1, 2]的最优解, 求出一次, 下一次就可以直接用(因为a[i-1, 1] 和 a[i-1, 2]都能分解出同样的子问题, 因此重叠了). 本题的每一步选择空间只有2个(流水线只有两条), 因此在每一步的子问题只有两个, 只需 最优(子问题1最优解+ 当前选择1, 子问题2最优解+当前选择2).


而对第二道题, 矩阵相乘次序, 步进式体现在选择括号上, 第一次选择括号, 有(1~N)个选择, 因此子问题也划分为这么多,而DP的优势在于这些子问题在进一步求解中会产生重叠子问题, 因此真正需要求出的其实是 1<=i<=j<=N 的组合的最优解, 共有N2次方个。

E.g, 第一次分割遍历子问题, 到了i, 1~i, i~N, 求出了 1 ~ i的最优解, 而对于j > i 来说 求出 1~j的最优解 是会依赖1~i的最优解的, 这就是重叠子问题了.    


在举一个更常见的题, 求某数组A的连续最大和, 这道题其实真分析起来, 是包含了两个DP的,

一个DP 是真正的求此数组1 ~ i range内的最大连续和   S[i]

第二个DP则是求此数组从结尾i开始的最大连续和 ES[i]

而当前1~i+1 range的最大连续和则是 S[i+1] =  max(S[i], ES[i] + A[i+1], A[i+1]).  而 ES[i+1] = max(ES[i] + A[i+1], A[i+1]);

可以看到 ES其实也是DP, 所以本题会维护两个辅助队列。 之所以这样, 也是因为连续和的特殊性质决定的(数组尾加上一个新数, 必须在上面那3者中进行对比).

ES[i-1]其实就是重叠子问题.







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值