昨天学习了(准确地说是复习)01背包问题,今天学习利用滚动数组来进一步精简代码,今天所参考的是这篇文章:https://mp.weixin.qq.com/s/M4uHxNVKRKm5HPjkNZBnFA
从递推公式 f[i][j] = max(f[i-1][j] , f[i-1][j-weight[i]] + value[i])中可以看出,利用滚动数组的思想,完全可以将i这一层去掉,从而:f[j] = max(f[j] , f[j-weight[i]) + value[i]),所以只需使用一维数组即可。
int main() {
vector<int> weight{ 1 , 3 , 4 };
vector<int> value{ 15 , 20 , 35 };
int bagweight = 4;
vector<int> f(bagweight + 1);
//f[j]表示在最大重量为j的背包中,选择放入物品可得到的最大价值
for (int i = 0; i < weight.size(); i++)
{
for (int j = bagweight; j >= 0; j--)
{
if(j >= weight[i])
f[j] = max(f[j], f[j - weight[i]] + value[i]);
}
}
cout << f[bagweight];
return 0;
}
关于初始化:
由于f[0]表示在最大重量为0时,可得到的最大价值,所以初始化为0即可。
关于递归:
这里的两层递归,遍历背包时,一定要从大到小,否则可能会出现同一样物品多次放入背包中的情况,例如:
而使用二维数组时,对背包就可以从小到大遍历,因为二维数组在遍历第i层时,使用的是第i-1层的数据,不会出现数据被覆盖的情况。
此外,也不能先遍历背包后遍历物品,必须先物品后背包,因为前者会导致背包中只能放入一件物品。