完全背包问题总结
每个物品是无限制的
也包括组合问题,排列问题:排列问题背包在外层遍历,组合问题物品在外层遍历。
- 与01背包问题最大的不同是,因为一个物品可以装多次,==背包从前往后遍历==。
- 组合问题不强调顺序,排列问题强调元素之间的顺序。

组合问题
有多少种方法。
- 递推公式:
dp[j] = dp[j] + dp[j - nums[i]]
- 初始化:
dp[0] = 1
- 外层遍历物品,内层遍历背包
遍历模板:
1 2 3 4 5
| for(int i = 0; i < coins.length; i++){ for (int j = coins[i]; j <= amount; j++){ dp[j] = dp[j] + dp[j-coins[i]]; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Solution { public int change(int amount, int[] coins) { int[] dp = new int[amount + 1]; dp[0] = 1; for(int i = 0; i < coins.length; i++){ for (int j = coins[i]; j <= amount; j++){ dp[j] = dp[j] + dp[j-coins[i]]; } } return dp[amount]; } }
|
- 这个最重要的是要,跳过初始值。
- 初始化:
dp[0] = 0, 0的时候最少就是啥也不用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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]; } }
|
排列问题
遍历模板:
1 2 3 4 5 6 7
| for (int i = 0; i <= target; i++){ for (int j = 0; j < nums.length; j++){ if (i >= nums[j]){ } } }
|
- 这是一道,组合与排列相结合的题目
- 题目强调:顺序不同的序列被视作不同的组合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution { public int combinationSum4(int[] nums, int target) { int[] dp = new int[target + 1]; dp[0] = 1; for (int i = 0; i <= target; i++){ for (int j = 0; j < nums.length; j++){ if (i >= nums[j]){ dp[i] = dp[i] + dp[i-nums[j]]; } } } return dp[target]; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution { public int climbStairs(int n) { int[] dp = new int[n+1]; dp[0] = 1; for (int i = 0; i <= n; i++){ for (int j = 1; j <= 2; j++){ if (i >= j){ dp[i] = dp[i] + dp[i-j]; } } } return dp[n]; } }
|