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背包状态方程
}
}
}
}