动态规划擅长求解最优解问题
最长递增子序列(LIS)
有序列{a1,a2,…,an}如{3 4 0 1 2},我们求其最长递增子序列长度。
第一步,分解问题
显然,最长递增子序列长度 = max { 以3结束的递增子序列的最长长度,以4结束的递增子序列的最长长度,以0结束的递增子序列的最长长度,以1结束的递增子序列的最长长度,以2结束的递增子序列的最长长度 }
新建数组F,用F[i]代表以ai结束的递增子序列的最长长度。当 i 较小,我们容易直接得出其值,如 F[1] = 1。
仔细思考,划分问题得到了多个子问题,其中“以3结束的递增子序列的最长长度”是最简单的,可以直接计算得到,而后面的子问题越来越复杂,比如“以2结束的递增子序列的最长长度”等,这就不是一眼能看出来的了。但我们仔细观察发现,后面的复杂子问题的求解依赖于前面的简单子问题的解。
于是可以求出一个动态规划的状态转移方程
得到状态转移方程
F[x] = max{1,F[i]+1|ai<ax && i<x};
序列 3 4 0 1 2
F[x] 1 2 1 2 3
比如我们考虑以1结束的递增子序列的最长长度:
要考虑1在3、4、0后面的情况
{x,3,1} {x,4,1}不会是正确的递增子序列,因为1比3,4要小,但是{0,1}会是一个正确的递增子序列,而{x,0}的最大长度为1,所以F[4]=max{1,F[3]+1}=2
当我们求出所有的Fn,再取出其中的最大值就是最长递增子序列长度
Fn的求解取决于前面的值,通过这样的Fn记录状态,不用重复计算Fn前面的
动态规划:合适地分解问题,使问题成为子问题1,2,3等,和分治法的不同之处在于,子问题的求解方式存在重复,通过状态转移方程使复杂子问题的求解可以通过简单子问题的解得到
leetcode
https://leetcode-cn.com/problems/maximum-subarray/
最大子序和
分解问题
显然,最大子序和=max{ 以第1个元素结尾的连续子数组的最大和, 以第2个元素结尾的连续子数组的最大和,以第3个元素结尾的连续子数组的最大和…}
以Fn存放第n个元素结尾的连续子数组的最大和
显然
Fn+1 = max(Fn+ai, ai)
序列 -2,1,-3,4,-1,2,1,-5,4
Fn -2,1,-3,4, 3,5,6, 1,5
最大子序和为6