- 递归/回溯,有太多做了重复的计算,我们要避免这个问题
- 分治、动态规划的联系
- 动态规划和分治的相同点:都是将原问题分解为若干个规模较小的子问题,递归的求解这些子问题,然后合并子问题的解得到原问题的解。
- 不同点:分治一般用来解决
子问题相互独立
的问题。而动态规划用来解决子问题重叠
的问题。所以,用动态规划能解决的问题分治策略肯定能解决,但是,运行时间更长。
- 贪心
- 换零钱:完全背包问题-求解最小的使用个数
- 现有面值为2、5、7,
最少
用多少枚硬币,拼出27元?(力扣322)
- 现有面值为2、5、7,
- 计算步骤:4个组成部分
-
确定状态
- 找最后一步
- 子问题
-
转移方程
f[x]=min{ f[x-2]+1, f[x-5]+1, f[x-7]+1 }
- f[x]表示,
最少
用多少枚硬币,拼出X元。1表示最后一枚硬币。
-
初始条件、边界情况
- 边界情况。如果f[x]下标为非法值,比如负数。就直接返回正无穷
- f[x]= +∞ 表示,无法用硬币拼出X元。
- 初始值。这里,f[0]=0。为什么需要初始值?-----如果使用转移方程,那么f[0]=+∞。但是我们明明知道f[0]=0。所以,对于转移方程算不出来的、但是又需要的状态,就只能手工定义。(初始条件)
- 边界情况。如果f[x]下标为非法值,比如负数。就直接返回正无穷
-
计算顺序
- 初始条件f[0]=0
- 计算f[0], f[1], ... , f[27] (这里是小->大)
-
时间复杂度 3*27.
-
# 初始化 base case
dp[0][0][...] = base
# 进行状态转移
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 求最值(选择1,选择2...)