背包问题小详解

背包问题是dp的一种分类。今天是对背包问题的一些归纳以及总结
背包大体分为三种背包,分别是01背包,完全背包以及多重背包

1、01背包:题目多为这样的:现在有一个背包(容器),它的体积(容量)为V,现在有N种物品(每个物品只有一个),每个物品的价值W[i]和占用空间C[i]都会由输入给出,现在问这个背包最多能携带总价值多少的物品?

01背包针对的是多个物品对应一定的容量以及价值,有不用和只用一次两种选择,那么对于任意一个物品,如果此时的背包内存小于物品的大小,我们就不把这个物品放进去,如果我们可以把这个物品放进去

我们需要考虑放进去这个物品是否对全部来说是最优解

for(ll i=1;i<=n;i++)//第i个物品
        for(ll j=v;j>=0;j--)//剩余空间j
        {
            if(j >= c[i])//如果装得下
                    f[i][j]=max( f[i-1][j-c[i]]+w[i],f[i-1][j]);
            else//如果装不下
                f[i][j]=f[i-1][j];
        }
主要实现的代码//
但是这样的01背包需要的内存是nv的,我们可以对此进行一定的优化
 for(ll i=1;i<=n;i++)//第i个物品
        for(ll j=v;j>=1;j--)//剩余空间j
        {
            if(f[j]<=f[j-c[i]]+w[i] && j-c[i]>=0 )//二维数组变一维数组
                 f[j]=f[j-c[i]]+w[i];//如果值得改变并且j的空间还装得下就赋新值
        }


2、完全背包:这个背包指的是对于任意物品可以取任意多次
那么其动态转移方程应该是for(int i=1;i<=t;i++) { for(int j=w[i];j<=m;j++) { dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } }
因为可以取多次,所以需要的是和第i个(本身)比较而不是第i-1个


3.多重背包:对于一些物品给定一些次数

可以运用二进制压缩的方法把他变成01背包去处理
or(int j=1;j<=a[i];j*=2) { num++; nw[num]=w[i]*j; nv[num]=v[i]*j; a[i]-=j; }//压缩优化 if(a[i]) { num++; nw[num]=w[i]*a[i]; nv[num]=v[i]*a[i]; a[i]=0; }



(大纲在这,后续再慢慢补)
posted @ 2021-02-02 21:40  Treasure-  阅读(156)  评论(0)    收藏  举报