背包问题
我实在是太弱了,这种东西才会这么点
分类
- 完全背包[√]
- 01背包[√]
- 多重背包[√]
- 毫无人性的乱七八糟的坑人专用背包[X]
定义
首先背包有一个共同的定义:有n种物品,每件物品都有一个价值vi和一个重量wi。(具体每件物品有几件,物品之间有什么主从关系是有分别的)
我们现在有一个背包,容量为c,我们要在容量范围之内(可以不装满)尽量装下价值最大的物品。
完全背包
完全背包的物品数量没有限制,也就是说,每件物品能取无数件。
01背包
顾名思义,每件物品都只能拿一个,每一个都有选和不选(1,0)两个状态
多重背包
和完全背包有些相似,但每种物品只能取ki个
解决方案
背包问题有一个共同的解题模板:f[0…n][0…c]数组,f[i][j]表示当前的背包容量为j,在前i件中所能达到的最大值。f[n][c]就是最终答案
(然而,还有一种优化方案:f[0…c]。在第j重循环中,f[i]表示当前背包容量为i时,在前j种物品中所能达到的最大值。因为f[]是从后往前计算的,所以f[i-w]是j-1种物品在容量为i-w时所能达到的最大值。所以f[i-w]+v等价于f[j-1][i-w]+v)
1. 完全背包
完全背包的物品数量没有限制,也就是说,每件物品能取无数件。
int w, v;
for(int i=1; i<=n; i++){
cin>>v>>w;
for(int j=w; j<=c; j++){
/*注意这里是正序枚举!!*/
f[j] = max(f[j], f[j-w]+v);
//等价于
//f[i][j] = max(f[i-1][j], f[i-1][j-w]+v);
}
}
2. 01背包
顾名思义,每件物品都只能拿一个,每一个都有选和不选(1,0)两个状态
int w, v;
for(int i