RE:StudyDiary——完全背包问题(2020/9/6)

01背包问题学习日记 (注:若未学习01背包请首先学习01背包)
今天学习的是01背包的变式——完全背包问题
题目如下

有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。
第 i 种物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

完全背包问题与01背包问题极其相似
其唯一的区别在于01背包一件物品只能装一次,而完全背包一件物品可以装多次
下面我们讨论如何推断完全背包问题的状态方程

我们先来看一段01背包的核心代码

	for(int i = 1;i <= n;i ++)
		for(int j = m;j >= v[i];j --)
			f[j] = max(f[j],f[j - v[i]] + w[i]);

01背包在一维数组下实现我们需要保证第i次循环所用的数据是第i-1次循环的状态,也可以理解为我们在更新第i个物品对一维数组的影响时应在已更新了第i-1个物品的影响的基础上进行,所以01背包在里循环里需要用从大到小的顺序来更新,而在完全背包问题中我们不需要考虑这样的问题,我们只需要考虑维护第i个物品对一维数组的影响即可(不用在意数组是否是从第i-1次循环里继承的)
核心代码如下

    for(int i = 1;i <= n;i ++)
        for(int j = v[i];j <= m;j ++)
            f[j] = max(f[j],f[j - v[i]] + w[i]);

我们可以看到完全背包的代码与01背包的代码的区别仅在于一个是顺向循环一个是逆向循环,对于这一点理解起来可能有一点困难,但其实我在01背包里讨论过这个问题,在这里你可以理解为我们在更新第i件物品的时候一维数组可能已经受了第i个物品的影响,因为是顺序进行的,所以我们是先更新了小容量的背包再更新大容量的背包,导致我们在改变状态时的一维数组可能已经受了第i个物品的影响

最后是AC的代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 1010;
int n,m;
int v[maxn],w[maxn];
int f[maxn];

int main()
{
    cin>> n >> m;
    for(int i = 1;i <= n;i ++) cin>> v[i] >> w[i];
    for(int i = 1;i <= n;i ++)
        for(int j = v[i];j <= m;j ++)
            f[j] = max(f[j],f[j - v[i]] + w[i]);
    cout << f[m];
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值