背包问题
背包问题
1、0-1背包(f[v]表示容量为v的背包的最大价值)
题目:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
特点:每个物品只可取一次
对于每种物品策略:取 || 不取
l f[i][v]=max(f[i-1][v],f[i-1][v-c[i]]+v[i])
不放第i 件物品的价值:f[i-1][v],问题转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];
放入第i 件物品的价值:f[i-1][v-c[i]]+v[i], 问题转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”
主体代码:
for i=1..N //第几件物品
for v=V..0 //装入前i件物品,背包容量为v时的最大价值
f[v]=max{f[v],f[v-c[i]]+w[i]};
初始化:
若要求恰好装满背包:将f[0]初始化为0,其余f[1…N]初始化为-∞,此时只有f[0]的初始值是有意义的,其余的背包都无意义
若不要求装满,值需要得到最大价值的背包:将f[0…N]都初始化为0
2、完全背包
题目描述:
有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
特点:物品可以重复取
对于每种物品策略:取0次、 取1次、2次…
l f[i][v]=max(f[i-1][v-c[i]*k]+k*w[i],0<=k*c[i]<=V)
代码描述:
fori
=1..N
for
v
=0..V
f
[v
]=max
{f
[v
],f
[v
-cost
]+weight
}:
3、多重背包
题目描述:
有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
特点:可重复取,但每种物品取的次数固定
解题策略:将每个物品可取的次数n[i]分成不同n份,放入背包,变成0-1背包问题。分组时,可以将每个n分为几个数,使0-n中的每个数都可以由这些数组合得到。(如:10可以由:1 2 4 3组合得到)
代码描述:
//n个物品,背包容量为m
struct Good{
int c,w;
};
Vector<Good>good;
for(int i=1;i<=n;i++){
cin>>c>>w;
for(k=1;k<=s;k=k*2){
s-=k;
push_back(c*k,w*k);
}
}
for(auto good:goods)//对于goods中的每一个物体
for(int j=m;j>=good.c;j++)
f[j]=max(f[j],f[j-good.c]+good.w);
4、混合背包问题
判断当前物品属于哪一类,分别用不同背包问题的解决方案
解题策略:顺序:0-1背包、多重背包、完全背包
5、二维费用背包问题
题目描述:
二维费用的背包问题是指:对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a[i]和b[i]。两种代价可付出的最大值(两种背包容量)分别为V和U。物品的价值为w[i]。
特点:背包的限制增加一维
要点:状态增加一维,增加一维循环
f[i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}
6、分组背包问题
题目描述:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
特点:与0-1背包问题类似
要点:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值
状态转移方程:
f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于组k}
核心代码实现:
for 所有的组k
for v=V..0
for 所有的i属于组k
f[v]=max{f[v],f[v-c[i]]+w[i]}
7、有依赖的背包问题
题目描述:
这种背包问题的物品间存在某种“依赖”的关系。也就是说,i依赖于j,表示若选物品i,则必须选物品j。为了简化起见,我们先设没有某个物品既依赖于别的物品,又被别的物品所依赖;另外,没有某件物品同时依赖多件物品。
解题策略:把每一个主件和它所有附件的集合当成一个背包问题,求出每一个主件选择的最优解,再把已经是最优搭配所有的选择构成一个背包问题,最初得出最后的最优解