【01 バックパック理論】 01 バックパック問題 dp[j] (ローリング配列) <動的プログラミングボード>

[01 バックパック理論] 01 バックパック問題 dp[j]

n 個のアイテムと最大重量 w を運ぶことができるバックパックがあります。
i 番目の項目の重みをweight[i]、得られた値をvalue[i]とします。
各アイテムは 1 つだけあり、バックパックに入れるアイテムのうち、アイテムの合計値が最も大きいものを見つけます。

答え

動的プログラミング

  • dp 配列と添え字の意味を決定します
    。ローリング配列dp[j]:jの容量を持つバックパックは、最大値 のアイテムを運ぶことができます。dp[j]

  • 容量 のバックパックが運ぶ最大値
    dp[j]となる再帰式を決定します。容量 のバックパックが運ぶ最大値を表すと推定できます。容量にアイテムの価値を加えたバックパックを表します。(つまり、アイテムを入れた後の容量 のバックパックの値は次のようになります:) 2 つのオプションがあります:j
    dp[j]dp[j - weight[i]]dp[j - weight[i]]j - weight[i]dp[j - weight[i]] + value[i]j - 物品i重量ijidp[j]
    dp[j]

    • 1 つはそれ自体を取得する方法で、dp[j]これは 2 次元の dp 配列に相当しますdp[i-1][j]。つまり、項目は配置されませんi(前回と同じ)。
    • 一つは、 を取るdp[j - weight[i]] + value[i]、つまり項目を入れてi最大値を指定するというもので、結局は最大値を求めるというものです。
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  • dp配列を初期化する方法

dp[j]表します:j容量が のバックパックの場合、運べるアイテムの値は までです。dp[j]まず、dp[0]=0です
。dp 配列を導出するときは、最大値の数値を取得する必要があります。値が の場合、質問で与えられたすべてが正の整数である場合、添え字は0ではありません。それらをすべて0に初期化するだけです。つまり、他の添え字の値はすべて0に初期化されるため、dp配列は最大値を取ることができます初期値によって上書きされるのではなく、再帰式プロセス中に。

  • 横断順序を決定します。2
    次元 dp を横断する場合、バックパックの容量は小さいものから大きいものになります。1 次元 dp を横断する場合、バックパックの容量は大から小さいものになります。アイテムは最初に順方向に配置され、次にバックパックに詰められます
    。逆順のトラバーサルは、項目がi1 回だけ挿入されることを保証するものです。正の順序でトラバースすると、項目 0 が複数回追加されます。
for(int i = 0; i < weight.size(); i++) {
    
     // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) {
    
     // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}
  • dp 配列を推測する (dp 配列を出力する) 例として、
    バックパックの最大重量が 4 であるとします。もの:
重さ 価値
アイテム0 1 15
項目 1 3 20
項目 2 4 30

ここに画像の説明を挿入します

public class Solution {
    
    
    public static void main(String[] args) {
    
    
        int[] weight = {
    
    1, 3, 4};
        int[] value = {
    
    15, 20, 30};
        int bagWight = 4;
        testWeightBagProblem(weight, value, bagWight);
    }

    public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight){
    
    
        int wLen = weight.length;
        //定义dp数组:dp[j]表示背包容量为 j 时,能获得的最大价值
        int[] dp = new int[bagWeight + 1];
        
        //遍历顺序:先遍历物品,再遍历背包容量(倒序)
        for (int i = 0; i < wLen; i++){
    
    
            for (int j = bagWeight; j >= weight[i]; j--){
    
    
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        
        //打印dp数组
        for (int j = 0; j <= bagWeight; j++){
    
    
            System.out.print(dp[j] + " ");
        }
    }
}

おすすめ

転載: blog.csdn.net/qq_44033208/article/details/132640280