问题描述
笔记
通常这种动态规划的问题需要建一个表作为缓存,然后搞清楚每个元素的含义,以及元素之间的递推关系。
在这里建立一个二维表buff,行号i代表第几件物品,列号j代表背包容量。以物品w=[2,3,5,7]
和容量m=11
为例。buff[i][j]
的含义是考虑第i件物品,容量为j的时候,所能放下的最大容量。那么,递推关系应该是:
buff[i][j] = max(buff[i-1][j], buff[[i-1][j-w[i]]+w[i])
可以认为buff[i-1][j]是考虑完了第i-1件物品,现在要考虑第i件物品了。可能的操作是,放入第i件物品,或者不放。
1. 不放。那就是buff[i-1][j]。
2. 放。给当前情况腾出w[i]这么大的空间,看一下buff[i-1][j-w[i]]最大能装到多少,再把当前物品装进去。
最后的结果就取两者的较大值。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
1 | 0 | 0 | 2 | 3 | 3 | 5 | 5 | 5 | 5 | 5 | 5 | 5 |
2 | … |
最后还可以省下一些空间,只用一行数据,后来的数据覆盖这一行的数据即可。使用这种办法的话需要从后往前计算,防止覆盖”上一行“的值。
代码
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) {
// write your code here
const int nItem = A.size();
int buff[m+1];
for (int i = 0; i <= m; i++)
buff[i] = 0;
for (int j = 0; j < nItem; j++)
{
for (int i = m; i >= A[j]; i--)
{
buff[i] = max(buff[i], buff[i-A[j]]+A[j]);
}
}
return buff[m];
}
};
背包问题2
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A & V: Given n items with size A[i] and value V[i]
* @return: The maximum value
*/
int backPackII(int m, vector<int> A, vector<int> V) {
// write your code here
int buff[m+1];
for (int i = 0; i <= m; i++)
buff[i] = 0;
const int nItem = A.size();
for (int j = 0; j < nItem; j++)
{
for (int i = m; i >= A[j]; i--)
{
buff[i] = max(buff[i], buff[i-A[j]]+V[j]);
}
}
return buff[m];
}
};