动态规划
从入门到放弃系列
题目特点
1.计数
- 有多少种方式走到右下角
- 有多少种方法选出k个数使得和是sum
2.求最大最小值
- 从左上角走到右下角路径的最大数字和
- 最长上升子序列长度
3.求存在性
- 取石子游戏,先手是否必胜
- 能不能选出k个数使得和是sum
做题步骤
例题1-最大最小值型
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1.确定状态
-
找到最后一步:最优策略中的最后一个决策
-
确定子问题
-
比如这题,最后一步就是最后有一个硬币ak,然后除掉这个硬币,前面的硬币加起来是amount-ak
-
不需要直到前面的k-1枚硬币是怎么拼出amount-ak的,但是就是拼出来了
-
因为是最优策略,所以前面拼amount-ak的硬币数一定要最少,不然就不是最优策略
-
所以问题就转化成了如何用最少的硬币拼出27-ak
-
问题一样,规模变小的问题叫做子问题
-
所以就找到了简化的定义 f(x)=最少用多少枚硬币拼出x
所以f(amount)=min{f(amount-coins[i])+1}(i=0.....coins.size()-1) 也就是最后一枚硬币可能的取值是coins[0]到coins[size-1],拼出amount-coins[i]所需要的最小硬币数的最小值+1就是最终的解
-
2.写出转移方程
- 设状态f[x]=最少用多少枚硬币拼出x
- 对于任意x,f[x]=min{f[x-2]+1,f[x-5]+1,f[x-7]+1}
3.找到初始条件和边界情况
- 比如这题,边界条件就是f[x]中的x小于0,这个拼出来是负数显然不可能,那就用正无穷表示拼不出来
- 初始条件就是用转移方程算不出来,需要手动定义,0块钱需要0枚硬币f[0]=0,然后用f[0]就可以算出来f[1]
- 所以边界条件就是x<0,f[x]=INT_MAX,f[0]=0
4.确定计算顺序
- 确定从小到大还是从大到小
- 原