バックパックの容量はcで、n個のアイテムがあり、各アイテムの値はvです。ロードする必要のあるアイテムの合計量は、バックパックの容量を超えません。
入力フォーマット
1行目は、バックパックの容量c、アイテム数n
次に、スペースで区切られたn個のアイテムの重みと値を指定します
アウトプット
最大値
アイデア:
古典的なDP質問、ここでは2次元DPを使用します。横座標iは現在検討されている項目番号を表し、縦座標jは総容量を表すため、n行とc + 1列の2次元配列を作成します ベクトル<vector < int >> memo( n、vector < int >(c + 1、-1))、この配列の名前はメモです。
次に、状態方程式を検討します。2つの戦略があります。1つは、現在のアイテムを考慮せずに、メモ[i] [j] =メモ[i- 1 ] [j]を直接考慮する方法 と、現在のアイテムメモ[i]を考慮する方法です 。 [j] = max(メモ[i-1] [j]、v [i] +メモ[i- 1 ] [jw [i]])、つまり、最後の転送を現在のアイテムと直接比較します(追加された場合) 。
バックパックの容量を5に設定した場合、アイテム数は3で、3つのアイテムの情報は次のとおりです。
id | 0 | 1 | 2 |
重量 |
1 | 2 | 3 |
値 | 6 | 10 | 12 |
したがって、状態遷移に従って2次元配列を取得します。
アイテムID /容量 | 0 | 1 | 2 | 3 | 4 | 5 |
0 | 0 | 6 | 6 | 6 | 6 | 6 |
1 | 0 | 6 | 10 | 16 | 16 | 16 |
2 | 0 | 6 | 10 | 16 | 18 | 22 |
最終的に達成した最大の価値は22でした。
コード
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 5 名前空間std を使用 。 6 7 int main() 8 { 9 int c、n; 10 11 cin >> c >> n; 12 if(n == 0 ) 13は0を返します。 14 vector < int > w(n); 15 vector < int > v(n); 16 for(int i = 0 ; i <n; i ++ ) 17 { 18 cin >> w [i] >> v [i]; 19 } 20 21 vector <vector < int >> memo(n、vector < int >(c + 1、- 1 )); 22 23 for(int j = 0 ; j <= c; j ++ ) 24 { 25 memo [ 0 ] [j] =(j> = w [ 0 ]?V [ 0 ]:0); // 現在のバックパックを置くことができる場合はv [0]、それ以外の場合は0 26 } 27 28 for(int i = 1 ; i <n; i ++ ) 29 { 30 for(int j = 0 ; j <= c; j ++ ) 31 { 32 memo [i] [j] = memo [i- 1 ] [j ]; // 最初の戦略は、現在のアイテム 33 を直接無視することですif(j> = w [i])// 2番目の戦略は、現在の容量が現在のアイテムに収まるかどうかを最初に決定する必要があります 34 { 35 メモ[i] [j ] = max(メモ[i] [j]、v [i] +メモ[i- 1 ] [j- w [i]]); 36 } 37 } 38 } 39 40 cout << memo [n- 1 ] [c]; 41は 0を返し ます。 42 }