【算法笔记】动态规划Dynamic Programming

参考视频5 Simple Steps for Solving Dynamic Programming Problems

引子:最长递增子串(Longest Increasing Subsequence,LIS)

LIS([3 1 8 2 5]) = len([1 2 5]) = 3

LIS([5 2 8 6 3 6 9 5]) = len([2 3 6 9]) = 4

解决问题的三个步骤:

  1. 可视化例子(visualize example)

(“visualize example”应该是用数据结构表示问题的意思)

使用有向无环图作为工具(directed acyclic graph)

比如[3 1 8 2 5]的LIS的有向无环图就是1->2->5

求LIS的长度就是求有向无环图的最长路径+1

即:LIS = Longest Path in DAG + 1

假如A=[5 2 8 6 3 6 9 5],要求LIS[5],怎么办?

LIS[5] = 1 + max

  1. 找到问题的子问题(find a appropriate sub-problem)

所有递增子串是原序列的子集;所有递增子串都有头和尾,并且无论头还是尾节点都在原序列中;

因此可以改变头或者尾来得到一个子问题,这里选择尾节点,即:
LIS[k] = LIS ending at index k

例如对于[3 1 8 2 5],LIS[3] = 2,因为以index=3(即2)的节点为结尾,能找到的LIS就是[1 2],故长度为3。

  1. 找到各个子问题之间的关系

首先思考,在[3 1 8 2 5]中,LIS[4]和之前的子串的关系是什么?

答案是:以index=4为结尾的LIS的前一个节点,有可能是index=0,1,3三种情况(3->5,1->5,1->2->5)

故而要求最长的长度,就是在所有可能的情况中,选出一种最长的再加1,即LIS[4] = max{LIS[0], LIS[1], LIS[3]} + 1

若A=[5 2 8 6 3 6 9 5],求LIS[5]:

LIS[5] = 1 + max{LIS[k] | k < 5, A[k] < A[5] }

把解决方法规范一下就是
LIS[n] = 1 + max{LIS[k] | k < 5, A[k] < A[n] };

到了这里,问题基本解决了,不过还有个问题是,我们只记录了长度,如何知道具体的子串到底是什么?

答案是:可以在第3步时,记录下前一个点的位置。

posted @ 2023-11-01 22:08  码鸽  阅读(4)  评论(0编辑  收藏  举报