背包问题:代码实现

0-1背包

设n个物体,体积v,价值w,背包总容量M

状态转移方程:f[j]=max(f[j],f[j-v[i]]+w[i])

代码:

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]);
    }
}

完全背包

状态转移方程:f[j]=max(f[j],f[j-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]);
    }
}

 

多重背包

多重背包也和前两个类似,只不过多重背包是一个物品最可以取k次,然后求最大收益

一个很容易想到的点就是将第i个物品转化为k次,当做0-1背包去做,但是这样时间复杂度偏高,因此我们可以对此进行优化

二进制分组优化代码:

int cnt= 0;
for (int i = 1; i <= n; i++) {
  int c = 1, v, w, k;
  cin >> v >> w >> k;
  while (k - c > 0) {
    k -= c;
    list[++cnt].w = c * w;
    list[cnt].v = c * v;
    c *= 2;
  }
  list[++cnt].w = p * w;
  list[cnt].v = h * v;
}

这样就可以将k个压缩为log2(k)个,再套用0-1背包即可

混合背包

如果是0-1背包,就套用0-1背包代码

如果完全背包,就套用完全背包代码

如果是多重背包,就套用多重背包代码...

二维费用背包

在0-1背包基础上在增加一维即可

代码:

for(int i=1;i<=n;i++)
{
    for(int j=M;j>=v[i];j--)
    {
        for(int k=T;k>=t[i];k--)
        {
            f[j][k]=max(f[j][k],f[j-v[i]][j-t[k]]+w[i]);
        }
    }
}

分组背包

将物品分组,每个组内的物品相互冲突,只能选一个

对每一组进行一次0-1背包

代码:

for(int i=1;i<=n;i++)//循环每一组
{
    for(int j=M;j>=0;j--)//循环背包容量
    {
        for(int k=1;k<=cnt[k];k++)//循环组内每个物品
        {
            if(j>=v[t[i][j]])//如果背包容量大于该物品体积
            {
                f[j]=max(f[j],f[j-v[t[i][k]]+w[t[i][k]]);//0-1背包状态方程
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42428269/article/details/117404248