2021.9.3 利用滚动数组解决01背包问题

昨天学习了(准确地说是复习)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层的数据,不会出现数据被覆盖的情况。
此外,也不能先遍历背包后遍历物品,必须先物品后背包,因为前者会导致背包中只能放入一件物品。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值