DP回顾篇

前言:

知识真的是学习了,总结了,练习了,运用了,再次总结归纳了,但是还是会一点点遗忘。动态规划(DP)又是算法里面非常非常重要的部分,所以一定要再次复习一遍。

写这篇博客的时候不由想起上学期算法课上的一个小插曲。老师问有没有喜欢音乐的,一堆人举手。然后老师随便找了个黑人同学上去,让他用手在桌子上拍一首大家都知道的歌的节奏,让全班同学都来猜歌名。(全班70人左右)。拍了半天,有几个同学举手回答是什么歌都猜错了,最后有一个同学猜出来是Happy Birthday! 又换了几个人上去拍节奏,都是只有1个人猜出来。

老师最后总结,我们拍节奏的时候,觉得这首歌是每个人都知道的,别人应该能一下子听出来。但是事实情况是,只有一个同学猜对了。这就像我们传递信息时候,总以为别人肯定能理解我们的意思,但往往事实是相反的。老师教学生的时候觉得学生一定能听得懂自己在说什么,其实学生可能完全没听懂。学生在卷子上写的答案也是,觉得老师一定看得懂自己写的是什么,然后写得乱七八糟毫无格式,其实根本没有人看得懂这个答案。(恰逢刚考完期中考,老师特地拿这个例子来说他看不懂学生在写什么,要我们答案有格式,有段落)。就像我写博客也是,觉得别人一定能看得懂我写的,别人都有一定基础,然后不管没基础的人看不看得懂。可是我又不想很累的写得特别清楚特别细节,毕竟我不是教书,或者写书。

Dynamic Programming:

递归是自顶向下,需要不断开辟现场,结束现场,恢复现场,所以特别消耗性能,时间上还特别浪费。而DP是递归的反过来,通过自底向上,用空间换时间,大大减少了时间复杂度,性能又高。按自己理解瞎鸡儿说的,不是书上写的。

DP四步曲:

《DP回顾篇》

 

Notation大法是做DP的关键,从此麻麻不用再担心我不会思考DP算法了,接下来就是记录教材上DP的经典例子。

MATRIX CHAIN MULTIPLICATION:

矩阵链相乘:查找矩阵链相乘最小的计算次数。首先需要观察到以下几点:

 

  1. A1(r1xc1), A2(r2xc2), 如果矩阵A1XA2,需满足c1=c2
  2. 矩阵(axb)和矩阵(bxc)相乘,结果得矩阵(axc),cost time: axbxc
  3. [(A1A2)A3] = [A1(A2A3)] 但是cost time不同

1.Notation: 用 M(i,j) 表示矩阵Ai到Aj相乘的cost time。定义, M(i,i) 为0 for all i, 因为没有矩阵相乘cost time为0.

定义M(1,n)为所有n个矩阵的cost time。

2.Principle of Optimality: 矩阵相乘,可以用二叉树表示,如图。

《DP回顾篇》

假设树T表示矩阵Ai,Ai+1到Aj相乘, 它的子树left表示:B=Ai..Ak相乘,它的子树right表示Ak+1…Aj相乘,(i<=k<j),那么T的cost time就等于:cost of T = cost(L)+cost(R)+cost(BC)

反证法证明tree L是最优的:

假设存在L’比L更优, that is cost(L’) < cost(L),则 cost(T’) = COST(L’)+COST(R)+COST(BC) < COST(T),则T不是最优的。

因此,如果T是最优的,那么L就是最优的,R也是最优的。否则T就不是最优的。(反证法太TM无脑了,每每被无语到。)

3.Recurrence Relation: M(i,j) = M(i,k)+M(k+1,j)+RiCkCj. 因此,最小化的M(i,j)通过找到一个k使得M(i,k)+M(k+1,j)+RiCkCj 最小,其中, i<=k<=j-1.

4.Algorithm

《DP回顾篇》

因为有中间的k,所以矩阵相乘从间隔2个(ABC)开始,找出最小的cost time,再到间隔3个(ABCD)开始,一直到n-1

ALL PAIRS SHORTEST PATH (APSP)

给定有向图, 求所有节点对直接的最短路径。

 

  • 节点:1~n
  • W(i,j)表示i->j的距离。有向图,所以W(i,j)不一定等于W(j,i)

 

《DP回顾篇》

D(i,j,k) i到j的最短路径,经过的点可以是(1~k)里面的点。

《DP回顾篇》

leetcode 787. Cheapest Flights Within K Stops 题,不止求2点之间最短距离,而且限制了最多使用K个点。

MAXIMUM VALUE CONTIGUOUS SUBSEQUENCE (MVCS)

最大的连续子序列:给定一个实数序列X1,X2,…Xn(不需要是正数),寻找一个(连续的)子序列Xi,Xi+1,…Xj,使得其数值之和在所有的连续子序列数值之和中为最大。

O(n^3),暴力破解查找所有子序列的和。

《DP回顾篇》

O(n^2)的解法:优化暴力破解,把第3次循环拆出来做一次比较便成了O(n^2)

《DP回顾篇》

O(n)的解法:

notation: MVCS(i)表示最大的连续子序列end at position i,可以包括或不包括i

《DP回顾篇》

LONGEST INCREASING SUBSEQUENCE (LIS)

最长递增子序列,(非连续,连续太简单了)

example: 【1,7,2,8,4,1,6,11,3,15】 -> 找到递增子序列如【1,2,3,15】中最长的。

Observation: Size最多不超过n。 

notation: X(i) 为 end at position i 的最长递增个数。

O(n^2)的解法:

《DP回顾篇》

 

(未完待续,NP经典教材题太多了,做过然后忘了的更多了,慢慢整理)

点赞