1. LeetCode 518. 零钱兑换 II
题目链接:https://leetcode.cn/problems/coin-change-ii/description/
文章链接:https://programmercarl.com/0518.零钱兑换II.html
视频链接:https://www.bilibili.com/video/BV1KM411k75j/
思路:
硬币无限,即,完全背包
物品:coins
背包:总金额amount
重量:硬币金额
价值:组合数量
本题关键:求方案个数,则递推公式如下:
dp[j] += dp[j - coins[i]];
求组合,遍历顺序是先物品再背包;
求排列,遍历顺序是先背包再物品。
解法:
class Solution {
public int change(int amount, int[] coins) {
//硬币无限。即完全背包
//物品:coins
//背包:总金额amount
//重量:硬币金额
//价值:组合数量
// 1. 定义dp数组
// dp[i]表示总金额是i的组合数量
int[] dp = new int[amount+1];
// 2. 递推公式
// dp[j] += dp[j-coins[i]];
// 3. 初始化
dp[0]=1;
// 4. 遍历顺序 先物品再背包
for (int i=0;i<coins.length;i++) {
for (int j=coins[i];j<=amount;j++) {
dp[j] += dp[j-coins[i]];
}
}
return dp[amount];
}
}
2. LeetCode 377. 组合总和 Ⅳ
题目链接:https://leetcode.cn/problems/combination-sum-iv/description/
文章链接:https://programmercarl.com/0377.组合总和Ⅳ.html
视频链接:https://www.bilibili.com/video/BV1V14y1n7B6/
思路:
元素可以重复取 完全背包。又知,顺序不同的序列被视作不同的组合,即排列
物品:nums
背包:总和为target的背包
重量:物品的值
价值:组合个数
本题关键:是排列,而不是组合。
解法:
class Solution {
public int combinationSum4(int[] nums, int target) {
//元素可以重复取 完全背包
//顺序不同的序列被视作不同的组合,即排列
//物品:nums
//背包:总和为target的背包
//重量:物品的值
//价值:排列个数
//1. 定义dp数组
//dp[j] 总和是j的排列数
int[] dp = new int[target+1];
//2. 递推公式
//dp[j] += dp[j-nums[i]];
//3. 初始化
dp[0]=1;
//4. 遍历顺序 先背包再物品
for (int j=0;j<=target;j++) {
for (int i=0;i<nums.length;i++) {
if (j>=nums[i]) {
dp[j]+=dp[j-nums[i]];
}
}
}
return dp[target];
}
}
3. LeetCode 70. 爬楼梯 (进阶)
题目链接:https://kamacoder.com/problempage.php?pid=1067
文章链接:https://programmercarl.com/0070.爬楼梯完全背包版本.html
思路:
每次走多台阶数可以重复 即,完全背包
不同台阶的顺序不同,组合不同,即排列
物品:nums,每个物品的值为台阶数
背包:总台阶数是n的背包
重量:台阶数
价值:方法个数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner src = new Scanner(System.in);
String[] line = src.nextLine().split(" ");
int n = Integer.parseInt(line[0]);// 总共台阶数
int m = Integer.parseInt(line[1]);// 每次至多m个台阶
int[] nums = new int[m];
// 物品
for (int i=0;i<m;i++) {
nums[i] = i+1;
}
// 每次走多台阶数可以重复 即,完全背包
// 不同多组合台阶是不同的,即排列
// 物品:nums
// 背包:总台阶数是n的背包
// 重量:台阶数,每个物品的值为台阶数
// 价值:方法个数
// 1.定义dp数组
// dp[j] 表示总台阶数是j含有的所有方法个数
int[] dp = new int[n+1];
// 2.递推公式
// dp[j] += dp[j-nums[i]]
// 3.初始化
dp[0] = 1;
// 4.遍历顺序 先背包再物品
for (int j=0;j<=n;j++) {
for (int i=0;i<nums.length;i++) {
if (j >= nums[i]) {
dp[j] += dp[j-nums[i]];
}
}
}
System.out.println(dp[n]);
}
}