动态规划:
动态规划(Dynamic Programming,简称DP),需要分解出问题的子结构以及通过子结构重新构造最优解。动态规划不像回溯法,有套路可以套用,动态规划需要大量练习,才能掌握规律。
一般思路:
1.判断问题的子结构(也可看作状态),当具有最优子结构时,就可能使用动态规划。
2.求解重叠子问题。一个递归算法不断地调用同一问题,递归可以转化为查表从而利用子问题的解。(注意与分治法区别开,分治法每次递归都产生新的问题)
特殊思路:备忘录法
备忘录法是动态规划的一种变形,最开始随机填一个数字,遇到子问题时,计算并填表。
实例可参照矩阵链乘法。
常见题目:
1. 硬币找零:假设有1,3,5三种硬币,数量无限,问当总额为某个值时需要最少硬币数为多少。
2. 装配线调度:某个工厂有两条装配线,汽车底盘经过每个流程时都有相应的时间消耗,问怎么安排,可以让进入流水线到出厂时,总时间最少。
3. 字符串相似度/编辑距离(edit distance)
有两个不同的字符串,只对一个字符串进行“增删改”操作,每次变化只有一个字符,问变成另一个字符串时,最少操作几次?
4.最长公共子序列(Longest Common Subsequence,LCS)
对于序列S和T,求它们的最长公共子序列。例如X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A}则它们的LCS是{B,C,B,A}和{B,D,A,B}。求出一个即可。
5.铺瓷砖问题(编程之美原题)
用 1 * 2 的瓷砖覆盖 n * m 的地板,问共有多少种覆盖方式?
6. 0-1背包
7. 有代价的最短路径
青蛙跳台阶问题。(这个和硬币找零很像)