問題の説明:
n個のアイテムがあり、それぞれに独自の重量と価値があります。特定の容量のナップザックがあります。ナップザック内のアイテムの価値の合計が最大になるようにするにはどうすればよいですか。
他の動的計画問題と同様に、この問題を解決するには2つの方法があります。
配列w[]はアイテムの重み、v[]はアイテムの値です
1つは再帰的なアイデアです。バックパックは、後ろから前に向かって、2つの値のサイズに基づいてアイテムを入れるかどうかを決定します(1つの値はバックパックに入れられていないアイテムの値であり、もう1つの値は、アイテムがバックパックに入れられることです。さらに、バックパックの容量により、アイテムの重量の値が減少し、2つの値の最大値になります。再帰的な終了条件は、アイテムが使い果たされるか、バックパックです。容量が0以下です。
dp
次は動的計画法のアイデアです。動的計画法は前から後ろに考えることです。
このナップサック問題を見つけるには、まずテーブルを描きます
横軸は容量、縦軸はアイテムIDです。
問題を解決するプロセスはこのテーブルを維持するプロセスであり、解決される値は最後のスペースの値です
アイテム0の最初
容量が0の場合、自重が1なので入れられないので、空欄に0を入れてください。容量が1の後に入れることができるので、6になります。
アイテムNo.1の場合
(2,1)の位置は、バックパックの容量が2なので、1番を入れたり、0番を取り出したり、1番を入れなかったりして、2つの場合の最大値を判断できます。これが最初の条件です。
この位置(3,1)の場合、バックパックの容量は3で、両方のアイテムを1,0に置くか、(2,1)を維持することができ、結果は両方のアイテムの最大値になります。
アイテムNo.2の場合
(3,2)この位置は、(0,1)+2アイテムの値と(3,1)のサイズであり、結果として(3,1)は比較的大きいため、16のままです。
(4,2)この位置は(1,1)+2アイテムの値であり、(4,1)はサイズよりも大きいため、結果は(1,1)+12になるため、18になります。
(5,2)この位置は(2,1)+2アイテムの値であり、(5,1)はサイズよりも大きいため、結果は(2,1)+12になるため、22になります。
したがって、最終的なバックパックの最大値は22です。
package action;
public class demo {
public static void main(String[] args) {
int size = 5;
int[] w = { 1, 2, 3 };
int[] v = { 6, 10, 12 };
System.out.println(backpack(w, v, size));
}
public static int backpack(int[] w, int[] v, int size) {
if (w.length != v.length)
return -1;
int n = w.length;
if (n == 0)
return 0;
int[][] memo1 = new int[n][size + 1];
for (int i = 0; i <= size; i++) {
memo1[0][i] = (i >= w[0] ? v[0] : 0);
}
for (int i = 1; i < n; i++) {
for (int j = 0; j <= size; j++) {
memo1[i][j] = memo1[i - 1][j];
if (j >= w[i]) {
memo1[i][j] = Math.max(memo1[i][j], v[i] + memo1[i - 1][j - w[i]]);
}
}
}
return memo1[n - 1][size];
}
}