問題
N 個の品物があり、それぞれ 1 から N までの番号が付けれらています。
品物 i の重さは整数値 wi であり、価値は整数値 vi です。
いくつかの品物を選んで持ち帰りたいのですが、品物を入れるナップサックには容量制限があり、重さの合計が W 以下になるようにする必要があります。
価値の合計としてあり得る最大値はいくらになるでしょうか。
[制約]
🔹1≦N≦100
🔹1≦Wi≦100000
🔹1≦wi≦W
🔹1≦vi≦109
解き方・ソースコード
この問題は次の二次元配列に対して、動的計画法を適用して解くことができます。
🔹dp[i][j] :品物1,2,…,N の中から、重さの合計が j となるように選ぶ。
このとき、合計価値としてあり得る最大値はいくつになるか。
まず、i=0の場合は、何も選ぶことができませんので重さや価値の合計は必ず 0 になります。
dp[0][0]=0 とし、他の値については十分に大きなマイナスの値 −1015 を設定しておきます。
次に、i≧1 の場合は、dp[i][j] の状態になる方法、つまり品物 i までの中から重さの合計が j になるように選ぶ方法として以下の2つだけが考えられます。
🔹方法A:品物 i−1 の時点で合計が j であり、品物 i を選ばない。
➡ dp[i−1][j]
🔹方法B:品物 i−1 の時点で合計が j−wi であり、品物 i を選ぶ。
➡ dp[i−1][j−wi]+vi
つまり dp[i][j] の値は、dp[i−1][j] と dp[i−1][j−wi]+vi のうち大きい方を選択します。
[Google Colaboratory]
1 | #--------- 入力例 ---------- |
注意が必要なのは、重さの合計がちょうど W のとき価値が最大になるとは限らないことです。
求める答えは dp[N][0],dp[N][1],…,dp[N][W] の最大値となります。
[実行結果]
解: 40
品物1、品物2,品物4を選んだ場合、重さの合計は[3 + 3 + 1 = 7]で価値の合計は[13 + 17 + 10 = 40]となりこれが価値の最大値となります。