バックパックの完全な理論的根拠
ビデオリンク:ナップザックの問題を完全に学習しましょう! 01バックパックとの違いは何ですか?走査順序の重要性は何ですか? _哔哩哔哩_bilibili
コンプリートバックパックと01バックパックの違いは、01バックパックの各アイテムは1回しか取得できないのに対し、フルバックパックの各アイテムは何度でも取得できることです。
リートコード 518. チェンジエクスチェンジ II
トピックリンク: 518. 変更交換 II - LeetCode
トピックの概要
さまざまな額面のコインと合計金額が表示されます。合計金額を構成するコインの組み合わせの数を数える関数を作成します。各金種のコインが無限にあると仮定します。
例 1:
入力: 金額 = 5、コイン = [1、2、5]
出力: 4
説明: 合計金額を切り上げるには 4 つの方法があります。
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
例 2:
入力: 金額 = 3、コイン = [2]
出力: 0
説明: 金種 2 の硬貨だけを使用して総額 3 を作ることはできません。
例 3:
入力: 金額 = 10、コイン = [10]
出力: 1
一連の考え
この質問は要素の順序を重視していません。例 1 と同様に、{221} と {122} は 2 つではなく組み合わせであるため、この質問は組み合わせの数を求めています (要素間の順序は重視されていません)。アイテムは無制限に取得できるため、この質問は完全なバックパックです。
まだ5部作のシリーズです
1. dp 配列と添字の意味を決定します。
dp[j]: 合計金額 j を構成する通貨の組み合わせの数は dp[j] です。
2. 再帰式を決定する
dp[j] += dp[j - コイン[i]] (バックパックを埋めるにはいくつかの方法があります。式は次のとおりです: dp[j] += dp[j - nums[i]]、この質問の式は定型的推論から導かれたこれに基づいています)。
3. dp 配列の初期化
dp[0] = 1。
4. 走査順序を決定する
完全なバックパックでは 2 層の for ループを逆にできると言われていますが、この質問は当てはまりません。for ループの 1 層目はお金 (アイテム) を走査し、for ループの 2 層目は走査します。合計量 (バックパック) バックパック全体の内容を特に強調する必要はありません。レイヤー ループは後ろから前にたどる必要があります。この質問に順序があるのは、求めているのが組み合わせの数であるためで、順序を逆にすると順列の数になります。
5. dp 配列を印刷する
コード
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1,0);
dp[0] = 1;
for(int i = 0;i < coins.size();i++) {
for(int j = coins[i];j <= amount;j++) {
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
};
リートコード 377. 組み合わせ和Ⅳ
トピックリンク: 377. 組み合わせ和 IV - LeetCode
ビデオリンク:ダイナミック プログラミング コンプリート バックパック、バックパックを埋める方法は何通りありますか? 順列の数を求めますか? | LeetCode: 377. 合計 IV_哔哩哔哩_bilibili
トピックの概要
個別の整数 の配列 nums
とターゲット整数が 与えられます target
。 合計が となる要素の組み合わせの数を調べて返してnums
ください 。target
質問データは、回答が 32 ビット整数の範囲内に収まることを保証します。
例 1:
入力: nums = [1,2,3]、ターゲット = 4 出力: 7 説明: 可能なすべての組み合わせは次のとおりです: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) ( 1 , 3) (2, 1, 1) (2, 2) (3, 1) 順序が異なるシーケンスは異なる組み合わせとしてみなされることに注意してください。
例 2:
入力:数値 = [9]、ターゲット = 3 出力: 0
一連の考え
この質問は実際には前の質問と似ていますが、唯一の違いは、この質問が順番に並んでいることと、順列の数が必要であることです。つまり、for ループの 2 つの層の走査順序が逆になっており、残りはほぼ同じです。変更なし。
まだ5部作のシリーズです
1. dp 配列と添字の意味を決定します。
dp[i]: 対象となる正の整数が i である順列の数は dp[i] です。
2. 再帰式を決定する
dp[i] += dp[i - nums[j]]。
3. dp 配列の初期化
dp[0] = 1。
4. 走査順序を決定する
for ループの最初の層はバックパックを走査し、for ループの 2 番目の層はアイテムを走査します。
5. dp 配列を印刷する
コード
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1,0);
dp[0] = 1;
for(int i = 0;i <= target;i++) {
for(int j = 0;j < nums.size();j++) {
if(i - nums[j] >= 0 && dp[i] < INT_MAX - dp[i - nums[j]]) {
dp[i] += dp[i - nums[j]];
}
}
}
return dp[target];
}
};