本章参考《算法图解》
动态规划先解决子问题,在逐步解决大问题。
仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用。
动态规划的核心原理是利用已经计算的数据,避免重复计算。
动态规划的三大步骤:(这里参考了 https://zhuanlan.zhihu.com/p/91582909)
①定义数组元素的含义。dp[]
②找出数组元素之间的关系式。用之前的数据计算当前的数据,即用dp[n-1],dp[n-2]…dp[1]来推出dp[n]。
③找出初始值。即dp[1],dp[2]等。
这就是数学归纳法。
下面参考:https://www.zhihu.com/question/23995189/answer/613096905
动态规划问题的无后效性:给定某一阶段的状态,在这一阶段以后过程的发展不受这阶段之前的各段状态的影响。例子:斐波那契数列,f(n)=f(n-1)+f(n-2),f(n)只与其之前的两个值有关,而与更前面的值无关。
最优子结构:大问题的最优解可以由小问题的最优解推出。
能用动态规划解决的问题:能将大问题拆成几个小问题,且满足无后效性、最优子结构性质。
DP快的原因是自带剪枝的。即它舍弃了一大堆不可能成为最优解的答案,尽量缩小了可能解空间。
背包问题
解决方法参考这里:https://zhuanlan.zhihu.com/p/45279233
1 | # coding:utf-8 |
最大上升子序列问题,参考这里:https://www.zhihu.com/question/23995189/answer/305426560
给定一个数列:1,7,2,8,3,4 它的最长上升子数列为:1,2,3,4 长度为4。
分析,暴力穷举法是列举出所有的上升子序列,再找出最长的,时间复杂度为O(n!)
原问题求LIS(n),现在需要找出LIS(n)和LIS(k)之间的关系,其中1<=k<=n。
人肉分析一下,LIS(k+1)要么等于LIS(k),即增加的一项比前面的尾项小或相等,要么等于LIS(k)+1,即增加的一项比前面的尾项大。
所以原问题和子问题的关系为
LIS(n) = max(LIS(1),LIS(2),…,LIS(n-1)) + (A(n) > A(n-1)? 1: 0)
实现代码:参考 https://www.cnblogs.com/anzhengyu/p/11166708.html
1 | # 动态规划求序列的最长子序列 |
我发文章的三个地方,欢迎大家在朋友圈等地方分享,欢迎点“在看”。
我的个人博客地址:https://zwdnet.github.io
我的知乎文章地址: https://www.zhihu.com/people/zhao-you-min/posts
我的微信个人订阅号:赵瑜敏的口腔医学学习园地