完全背包详解--模板

优先理解01背包:

推导:

我们列举一下更新次序的内部关系:

f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w ,  f[i-1,j-2*v]+2*w , f[i-1,j-3*v]+3*w , .....)
f[i , j-v]= max(            f[i-1,j-v]   ,  f[i-1,j-2*v] + w , f[i-1,j-3*v]+2*w , .....)
由上两式,可得出如下递推关系: 
                        f[i][j]=max(f[i,j-v]+w , f[i-1][j]) 



1.01背包和完全背包核心代码其实只有一句不同(注意下标)       

 f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);   //01背包

        f[i][j] = max(f[i][j],f[i][j-v[i]]+w[i]);   //完全背包问题


为什么完全背包变成了 i 呢,因为 每个物品都是可以随便选的,不像01背包只能选一次。
2.同样优化:
        核心代码:

for(int i = 1 ; i<=n ;i++)
    for(int j = v[i] ; j<=m ;j++)//注意了,这里的j是从小到大枚举,和01背包不一样
    {
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    }

为什么从前往后枚举呢,因为与01背包反过来,要保证是当前 i 层更新的,而不是第 i-1 层更新过来的。

点击跳转例题
代码:
 

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 10000;
int v[MAXN];    // 体积 
int w[MAXN];    // 价值 
int f[MAXN][MAXN];  // f[i][j], j体积下前i个物品的最大价值 

int main() 
{
    int n;
    int m;  // 背包体积 
    cin >> n >> m;
    for(int i = 1; i <= n; i++) 
        cin >> v[i] >> w[i];

    f[0][0] = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 0; j <= m; j++) 
        {
            f[i][j] = f[i - 1][j];  // 不选第i个物品//集合一定存在; 
            //再次更新集合,看是否有更大的解;
            if(j >= v[i])           // 可以选择第i个物品,状态方程见上面推导    
                f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
        }

    cout << f[n][m] << endl;
    return 0;
}

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值