問題描述
有n個物品和一個大小爲m的揹包. 給定一個數組A表示每個物品的大小, 一個數組V表示每個物品的價值.
那麼最多能裝入揹包的總價值爲多大?
用F(i, j)表示前 i 個物品放入大小爲 j 的揹包中所獲得的最大價值
這樣的話, 其實每當我們看到第i個商品的時候, 我們都有兩種選擇, 就是放進揹包或者是不放進揹包.
首先, 如果第 i 個物品的大小大於揹包的容量, 那麼這個物品不能放進揹包, 也就是說, 此時這所有的 i 個商品放入大小爲 j 的揹包中的最大價值爲 F(i - 1, j)
因爲第 i 個商品無法放入揹包中.
其次, 如果第 i 個物品的大小小於揹包的容量, 那麼我們要考慮的就是, 放進去能得到最大價值還是不放
如果我們選擇放第 i 個商品, 那麼我們要保證揹包的空間足以容納這個商品, 也就是說此時的 F(i, j) = F(i - 1, j - A[i]) + V[i];
如果不放第 i 個商品, F(i, j) = F(i - 1, j)
class Solution {
public:
int backPackII(int m, vector<int> &A, vector<int> &V) {
// write your code here
int col = m + 1;
int row = V.size() + 1;
vector<vector<int>> v(row);
for (auto & e : v)
{
e.resize(col, 0); //初始化, 保證第一行第一列全爲 0
}
for (int i = 1; i < row; ++i)
{
for (int j = 1; j < col; ++j)
{
if (A[i - 1] > j)
{
v[i][j] = v[i - 1][j]; //第 i 個商品的大小大於此時揹包的大小
}
else
{
//考慮第 i 個商品放和不放兩種情況中的最大價值
v[i][j] = max(v[i - 1][j], v[i - 1][j - A[i - 1]] + V[i - 1]);//注意第 i 個商品在給定數組中的索引是 i - 1
}
}
}
return v[row - 1][col - 1];
}
};
上述方法看做二維數組的話, 其實我們在修改二維數組第 i 行的數值時, 每一次只用到了 i - 1行的數值, 也就是說其實我們可以利用一維數組完成這個問題.
class Solution {
public:
int backPackII(int m, vector<int> &A, vector<int> &V) {
// write your code here
int n = m + 1;
int len = A.size();
vector<int> v(n, 0);
for (int i = 0; i < len; ++i)
{
for (int j = n - 1; j >= 0; --j)
{
if (A[i] > j)
{
v[j] = v[j];
}
else
{
v[j] = max(v[j], v[j - A[i]] + V[i]);
}
}
}
return v[n - 1];
}
};