参考资料:
题目描述:
给你一个整数数组 coins
表示不同面额的硬币,另给一个整数 amount
表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0
。
假设每一种面额的硬币有无限个。
题目数据保证结果符合 32 位带符号整数。
示例 1:
输入:amount = 5, coins = [1, 2, 5] 输出:4 解释:有四种方式可以凑成总金额: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1
思路分析:
物品可重复选取,是完全背包问题。
若是求组合,先遍历物品,再遍历背包。
若是求排列,先遍历背包,再遍历物品。
代码实现:
class Solution {
public int change(int amount, int[] coins) {
//dp[j]:凑出j元的组合数dp[j]
int[] dp=new int[amount+1];
dp[0]=1;//初始化,
for(int i=0;i<coins.length;i++){//物品
for(int j=0;j<=amount;j++){//背包,求组合
if(j-coins[i]>=0){
dp[j]+=dp[j-coins[i]];
}
}
}
return dp[amount];
}
}
题目描述:
给你一个由 不同 整数组成的数组 nums
,和一个目标整数 target
。请你从 nums
中找出并返回总和为 target
的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
示例 1:
输入:nums = [1,2,3], target = 4 输出:7 解释: 所有可能的组合为: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) 请注意,顺序不同的序列被视作不同的组合
思路分析:
此题求排列,所以先遍历背包,再遍历物品。
代码实现:
class Solution {
public int combinationSum4(int[] nums, int target) {
//dp[j]:组成j的组合总数是dp[j]
int[] dp=new int[target+1];
dp[0]=1;//
for(int j=0;j<=target;j++){//背包
for(int i=0;i<nums.length;i++){//物品,求排列
if(j-nums[i]>=0){
dp[j]+=dp[j-nums[i]];
}
}
}
return dp[target];
}
}
题目描述:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
输入描述
输入共一行,包含两个正整数,分别表示n, m
输出描述
输出一个整数,表示爬到楼顶的方法数。
输入示例
3 2
输出示例
3
思路分析:
求排列,先背包,再物品。
且此题遍历时需要从下标1开始遍历,否则结果会错
代码实现:
import java.util.Scanner;
class climbStairs{
public static void main(String [] args){
Scanner sc = new Scanner(System.in);
int m, n;
while (sc.hasNextInt()) {
// 从键盘输入参数,中间用空格隔开
n = sc.nextInt();
m = sc.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 >= 0) dp[j] += dp[j - i];
}
}
System.out.println(dp[n]);
}
}
}
01背包和完全背包
01背包
public int maxValue1(int[] w,int[] v,int size){
int res=0;
int n=w.length;
int[] dp=new int[size+1];//dp[i] 背包容量为i能装的最大价值
for(int i=0;i<n;i++){//物品
for(int j=size;j>=w[i];j--){//背包 倒序遍历,保证每个物品只取一次
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
// for(int j=0;j<=size;j++){
// System.out.print(dp[j]+" ");
// }
return dp[size];
}
完全背包
- 求组合
public int maxValue2(int[] w,int[] v,int size){
int n=w.length;
int[] dp=new int[size+1];
for(int i=0;i<n;i++){//物品
for(int j=0;j<=size;j++){//背包。(此时求组合)。正序遍历,且物品和背包先后顺序可交换
if(j-w[i]>=0){
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
}
return dp[size];
}
- 求排列
public int maxValue2(int[] w,int[] v,int size){
int n=w.length;
int[] dp=new int[size+1];
for(int j=0;j<=size;j++){//背包
for(int i=0;i<n;i++){//物品,排列
if(j-w[i]>=0){
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
}
return dp[size];
}