- バックパック
中文英語
サイズ愛と考えるN項目は、整数mは、バックパックの大きさを表します。どのように完全なあなたは、このバックパックを埋めることができますか?
実施例
実施例1:
入力:[3,4,8,5]、バックパックのサイズ= 10
出力:9
実施例2:
入力:[2,3,5,7-]、バックパックのサイズ= 12
出力:12
チャレンジ
O(n×m個)時間とO(M)メモリ。
O(n×mの)メモリを使用すると、メモリを最適化する方法がわからない場合も可能です。
注意してください
あなたが小片に任意の項目を分割することはできません。
溶液1:二次元配列の
コードは以下の通りであります:
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
int backPack(int m, vector<int> &A) {
int n = A.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; ++i) {
// for (int j = m; j >= A[i]; --j) {
// for (int j = A[i - 1]; j <= m; ++j) {
for (int j = 1; j <= m; ++j) { //也可以写成 for (int j = m; j >= 1; --j)
if (j >= A[i - 1]) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + A[i - 1]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][m];
}
};
注意:
- ループのための第二は、jは1を起動する必要があります。書かれた
ため(INT J = 1; J <= M; ++ j)を
と
するため(INT J = M; J > = 1; --j)
ことが可能です。
なぜの書き込み(INT J = M; J > = 1; --j)? それは2サイクルであるので、それはの[J] [i]を計算DP、jは下降、または小から大にされているかどうか、であってもよいです場合、DP [I - 1] [ J - [I - 1]は、 I-1の内側前回のサイクルで算出されていなければなりません。
なく、
用(INT M = J; J> = A [I]; --j){
DP [I] [J] = MAX(DP [I - 1]〜[J]、DP [I - 1] [ J - A [I - 1]] + A [I - 1]);
}
書き込むことができない
。 - ; J <= M; J ++){1](INT J = A [Iため
DP [I] [J = MAX(DP [I - 1]〜[J]、DP [I - 1] [J - A [I - 1。。。]] + A [I - 1]);
}
DPとして[I] [0 ... A [ I]]これは常にゼロとなっています。
2)I、Jおよび2つのループの位置を交換することができるため。
方法2:最適化された1次元配列
コードは以下の通りであります:
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
int backPack(int m, vector<int> &A) {
int n = A.size();
vector<int> dp(m + 1, 0);
for (int i = 0; i < n; ++i) {
for (int k = m; k >= A[i]; --k) {
//for (int k = A[i]; k <= m; ++k) { //wrong!!!
dp[k] = max(dp[k], dp[k - A[i]] + A[i]);
}
}
return dp[m];
}
};
注:
1)ループの第二は、(int型K = A [iについて書き込むことができない ; K <= M; ++ K)]。なぜ?なぜなら
内部DP [K] = MAX(DP - + A [i]が[K]、DP [A [i]がK])は、実際と同等である
DP [I] [K] = MAX(DP [I - 1] [K]、DP [I - 1] [K - [I] + [I])
kが降順である場合、DP [k]を計算DP [K - [I] ] -確かに[[i]のK DP ] 前のラウンドで。
[ - A [i]がK kが大きいに小さい場合には、次にDPときに算出[k]をDP ]は、 DPの現在のラウンド[ - A [i]がKです ]。そして、その結果は右ではありません。
2)上記の文言と本質的に同等です
int backPack(int m, vector<int> &A) {
int n = A.size();
vector<int> dp(m + 1, 0);
for (int i = 0; i < n; ++i) {
for (int k = m; k >= 0; --k) {
if (k >= A[i])
dp[k] = max(dp[k], dp[k - A[i]] + A[i]);
else
dp[k] = dp[k];
}
}
return dp[m];
}
しかしながら[K] = DP [K]余分な、第二サイクルに簡略化することができるDP
for (int k = m; k >= A[i]; --k) {
dp[k] = max(dp[k], dp[k - A[i]] + A[i]);