爬楼梯(进阶版)
时间限制:1.000S 空间限制:128MB
题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
输入描述
输入共一行,包含两个正整数,分别表示n, m
输出描述
输出一个整数,表示爬到楼顶的方法数。
输入示例
3 2
输出示例
3
提示信息
数据范围:
1 <= m < n <= 32;
当 m = 2,n = 3 时,n = 3 这表示一共有三个台阶,m = 2 代表你每次可以爬一个台阶或者两个台阶。
此时你有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶段
- 1 阶 + 2 阶
- 2 阶 + 1 阶
思路:本题与完全背包类似 ,可翻译为1到m个物品,重量分别是1,2....m,每个物品可以取多次,装满背包有多少种方法,注意2,1和1,2,是两种,这是完全背包的排列问题,关于完全背包的组合和排列问题,移步至
Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客
动态规划五部曲:
1.确定dp[j]的含义:
dp[j]:装满表示容量为j的物品,最多有几种方法
2.确定递推公式:
dp[j]+=dp[j-i];
3.dp数组如何初始化
dp[0]=1;如果dp[0]=1的话,后面推出来所以的值都为0
4.遍历顺序
一层循环遍历物品,一层循环遍历背包容量,哪层循环放外面?
Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客这篇文章有讲
由于本题中不同顺序算不同方法,所以应该用遍历背包容量在外层循环,遍历物品在内部循环
5.举例推导
代码参考:
import java.util.*;
class Main{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int m=in.nextInt();
int[] dp=new int[n+1];
//初始化
dp[0]=1;
//遍历容量/楼层
for(int j=1;j<=n;j++){
//遍历物品/步数
for(int i=1;i<=m;i++){
if(j>=i){
dp[j]+=dp[j-i];
}
}
}
System.out.println(dp[n]);
}
}
给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins =[1, 2, 5]
, amount =11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins =[2]
, amount =3
输出:-1
示例 3:
输入:coins = [1], amount = 0 输出:0
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104
思路:本题中每种硬币的数量是无限的,可以抽象成一道完全背包的问题
动态规划五部曲:
1.确定dp[j]的含义:
dp[j]:装满表示容量为j的物品,最少要几个物品
2.确定递推公式:
1).不放该硬币:dp[j]
2).放该硬币:dp[j-coins[i]]+1
dp[j]=min(dp[j],dp[j-coins[i]]+1)
3.dp数组如何初始化
求最少硬币数,为了防止覆盖,先将dp数组都设为Integer.MAX_VALUE
dp[0]=0;凑成0元只要0个硬币
4.遍历顺序
一层循环遍历物品,一层循环遍历背包容量,哪层循环放外面?
Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客这篇文章有讲
由于本题中不同顺序算同一方法,所以应该用遍历背包容量在内层循环,遍历物品在外部循环
5.举例推导
代码参考:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp=new int[amount+1];
//初始化
Arrays.fill(dp,Integer.MAX_VALUE);
dp[0]=0;
for(int i=0;i<coins.length;i++){
for(int j=coins[i];j<=amount;j++){
if(dp[j-coins[i]]!=Integer.MAX_VALUE)
dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);
}
}
return dp[amount]==Integer.MAX_VALUE?-1:dp[amount];
}
}
给你一个整数 n
,返回 和为 n
的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1
、4
、9
和 16
都是完全平方数,而 3
和 11
不是。
示例 1:
输入:n =12
输出:3 解释:12 = 4 + 4 + 4
示例 2:
输入:n =13
输出:2 解释:13 = 4 + 9
提示:
1 <= n <= 104
思考:
本题和上一题类似,转化为完全背包问题
1.确定dp[j]的含义:
dp[j]:装满表示容量为j的物品,最少要几个物品
凑成整数n,至少需要几个完全平方数
2.确定递推公式:
1).不放i*i:dp[j]
2).放i*i:dp[j-i*i]+1
dp[j]=min(dp[j],dp[j-i*i]+1)
3.dp数组如何初始化
求最少完全平方数,为了防止覆盖,先将dp数组都设为Integer.MAX_VALUE
dp[0]=0;凑成0只要0个完全平方数
4.遍历顺序
一层循环遍历物品,一层循环遍历背包容量,哪层循环放外面?
Day44:动态规划 LeedCode 完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ-CSDN博客这篇文章有讲
由于本题中不同顺序算同一方法,所以应该用遍历背包容量在内层循环,遍历物品在外部循环
5.举例推导
代码参考:
由于本题一定能凑出目标数,所以不需要判断dp[j-i*i]是否等于Integer.MAX_VALUE
class Solution {
public int numSquares(int n) {
int[] dp=new int[n+1];
Arrays.fill(dp,Integer.MAX_VALUE);
dp[0]=0;
for(int i=1;i*i<=n;i++){
for(int j=i*i;j<=n;j++){
dp[j]=Math.min(dp[j],dp[j-i*i]+1);
}
}
return dp[n];
}
}