题目:给定一个矩阵网络,一个机器人从左上角出发,每次可以向下或向右走一步
A:求有多少钟方式走到右下角(动态规划)
B:输出所有走到右下角的路径(递归)
动态规划题目特点:
1.计数
- 有多少种方式走到右下角
- 有多少种方法选出k个数使得和是sum
2.求最大最小值
- 从左上角走到右下角路径的最大数字和
- 最长上升子序列长度 Leetcode300 10
3.求存在性
- 取石子游戏,先手是否必胜
- 能不能选出k个数使得和是sum
例题
你有三种硬币,分别面值2元,5元和7元,每种硬币都有足够多
- 买一本书需要27元
- 如何用最少的硬币组合正好付清,不需要对象找钱(求最大最小值)
动态规划组成部分一:确定状态
解动态规划的时候需要开一个数组,数组的每个元素f[i]或者f[i][j]代表什么
- 类似于解数学题中x,y,z代表什么
- 最后一步
最后一步
keyOne: 我们不关心前面的k-1枚硬币是怎么拼出27-ak的(可能有1种拼法,可能有100种拼法),而且我们现在甚至还不知道ak和k,但是我们确定前面的硬币拼出27-ak。
keyTwo:因为是最优策略,所以拼出27-ak的硬币数一定要最少,否则这就不是最优策略了。
子问题
- 所以我们就要求:最少用多少枚硬币可以拼出27-ak
- 原问题是最少用多少枚硬币拼出27
- 我们将原问题转化为了一个子问题,而且规模更少:27-ak
- 为了简化定义,我们设状态f(x)=最少用多少枚硬币拼出x
- 我们还不知道最后那枚硬币ak是多少
- 最后那枚硬币ak只可能是2,5或者7
- 如果ak是2,f(27)应该是f(27-2)+1(加上最后这一枚硬币2)
- 如果ak是5,f(27)应该是f(27-5)+1(加上最后这一枚硬币5)
- 如果ak是7,f(27)应该是f(27-7)+1(加上最后这一枚硬币7)
- 除此以外,没有其他的可能了
- 需要求最少的硬币数,所以f(27)=min{f(27-2)+1,f(27-5)+1,f(27-7)+1}
int f(int x ){
//f(x)=最少用多少枚硬币拼出x
if(x==0) return 0; //0元钱只要0枚硬币
int res = MAX_VALUE; //初始化用无穷大
if(x>=2){
//最后一枚硬币是2元
res = Math.min(f(x-2)+1,res);
}
if(x>=5){
//最后一枚硬币是5元
res = Math.min(f(x-5)