简介
本文为复习动态规划的笔记,在UCLA CS180的笔记基础上增添了B站up主 七章算法的教学视频自学笔记内容
动态规划 - Dynamic Programming (DP)
DP 的定义是:
Consider a problem of size n
• Split the problem into smaller parts
把问题拆分为多个子问题
• The solution of the original problem can be iteratively computed based on the solutions of subproblems
在求解子问题的基础上,迭代求解原问题的解
DP的优点是:
Memorize the solution for solved subproblems
记住已解决的子问题的解
Reuse the stored solution when encounter again
再次使用存储的解决方案
也即是减少重复计算步骤,减少算法复杂度
OPT(i) : optimal solution with input size i(定义为当输入大小为i的最优解)
转换方程 Bellman Equation: O p t ( n ) = O p t ( n − 1 ) + O p t ( n − 2 ) Opt(n) = Opt(n-1) + Opt(n-2) Opt(n)=Opt(n−1)+Opt(n−2)
题目特点
下面图片来源于B站七章算法视频
题A用动态规划,动态规划一般就是给你最优解
题B用递归
计数型
- 多少种方式走到右下角
求最大最小值 (最常见)- 最优解
- 无数个途径 求最大数字和 。 最优策略
求存在性
-
取石子游戏 判断是否存在胜利策略
-
能不能选出k个数使和是Sum
动态规划组成部分:
-
确定状态:
- 最后一步
- 化成子问题
-
转移方程
-
初始条件和边界情况
-
计算顺序: 从小到大(原因:可以记录结果,不用重复计算)
例题
Coin Change 数硬币 - 求最值型动态规划
You are given an integer array
coins
representing coins of different denominations and an integeramount
representing a total amount of money.Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return
-1
.You may assume that you have an infinite number of each kind of coin.
即用最少的硬币数组合去付款。
Example 1:
Input: coins = [1,2,5], amount = 11 Output: 3 Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3 Output: -1
Example 3:
Input: coins = [1], amount = 0 Output: 0
Example 4:
Input: coins = [1], amount = 1 Output: 1
Example 5:
Input: coins = [1], amount = 2 Output: 2
思路
题型是多个组合求最大最小值,用动态规划解。
假设总计金额是amount = 50。 f ( 50 ) f(50) f(50) 就是这个问题的解,把这个问题拆分成子问题,使规模变小,求最优解。
不论哪个组合,都存在最后一步,即最后的一个硬币,它可以为任意值。
我们假设硬币有三种[1, 2, 5], 然后最少的硬币数设为k。即问题为 f ( 50 ) = k f(50)=k f(50)=k 枚。那么各组合中最后一枚$ a_k 必 定 为 这 三 者 的 其 中 之 一 。 那 么 , 剩 下 的 就 是 必定为这三者的其中之一。那么,剩下的就是 必定为这三者的其中之一。那么,剩下的就是k-1$枚硬币需要我们求最优解。
也就是说,已经问题拆分为三个子问题了,再根据每个子问题继续递归拆分成三个子问题的子问题,便可得最优解。
拆分完成,接着是第二步**转移方程 **。(为了提高效率,减少递归解法中的重复计算)
把问题转为 f ( x ) = f(x) = f(x)=min{ f ( x − 1 ) + 1 , f ( x − 2 ) + 1 , f ( x − 5 ) + 1 {f(x-1)+1, f(x-2)+1,f(x-5)+1} f(x−1)+1,f(x−2)+1,f(x−5)+1}, (+1是指最后一枚硬币),每一步都要计算三种方案。
第三步,初始条件和边界情况。
初始条件: f ( 0 ) = 0 f(0) = 0 f(0)=0
边界情况:如果拼不出Y,则 Y = ∞ Y= \infin Y=∞
f(0) | f(1) | f(2) | f(3) | f(4) | f(5) | f(6) | … | f(50) |
---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | - | - | 0 | 1 | ----- |
总计50步,每一步尝试三种硬币方案。
第四步,计算顺序。从小到大开始计算并记录之前的计算结果,那么后面的计算不需要重新计算之前的 f ( x ) f(x) f(x), 加快计算速度。
e.g. 换个例子说,5+2=7,如果要求5+2+7的话,因为我们已经知道5+2=7了,那么程序记录下来直接调用,计算就是 7+7=14, 不需要对5+2再进行重复的计算。