简单的背包问题及优化
“你的背包,让我走的好缓慢” ——陈奕迅
一、0-1背包
最简单的0-1背包问题,顾名思义,就是要么装,要么不装。难度不高,但也有一些很清(zhong)新(suo)脱(zhou)俗(zhi)的技巧来让它更巧妙。
E.G:SQ有N个物品,每个物品都有体积tj[i],价值c[i],有一个背包容积为V,在体积不超过V的前提下,背包中物品的价值最大是多少?
1.平淡无奇de解法一:
设f(i,v),其意义为考虑选择第i件物品和剩余空间时的当前总价值,
所以,容易得出两种情况——
不选第i个物品 | 选第i个物品 |
---|---|
f(i-1,v) | f(i-1,v-tj[i])+c[i]) |
则状态转移方程为:f(i,v)=max(f(i-1,v),f(i-1,v-tj[i])+c[i]),答案为f(N,V);
//由于解法一过于基础,在此未给出代码 (´・ω・`)
2.有意思的解法二
注意,在解法一中可以发现,f(i,v)只与f(i-1,v)或f(i-1,v-tj[i])有关联,也就是第i行第v列的格子只与第i-1行更靠左边的格子有关系。
把空间压缩到1维,第i行的格子倒着填,左边还没填的格子一定是保留的上一状态(i-1的状态),这样便可以实现空间优化了。
for(int i=1;i<=N;i++){
for(int v=V;v>=tj[i];v--){
//倒着枚举体积,要做减法所以不能减成负的
f[v]=max(f[v],f[v-tj[i]]+c[i]);
}
}
ans=f[V];
二、完全背包
E.G:SQ这次有了n种物品,每种物品都有体积tj[i],价值c[i],每种物品数量不限。有一个背包容积为V,在体积不超过V的前提下,背包中物品的价值最大是多少?
先上代码~
for(int i=1;i<=N;i++){
for(int v=tj[i];v<=V;v++){
//这次的空间优化需要正着枚举v,注意与0-1背包的区别
f[v]=max(f[v],f[v-tj[i]]+c[i]);
}
}
ans=f[V];
完全背包的特点是每种物品可选无限件(✪ω✪),考虑完i物品以后还要继续考虑**“加选一件第i种物品”**这种策略,所以需要一个可能已选入第i种物品的子结果,就可以并且必须采用正向的v=tj[i]~V的顺序循环。
三、多重背包
E.G:SQ再一次有了n种物品,每种物品依然有体积tj[i],价值c[i],但不同的是,每种物品数量n[i]。有一个背包容积为V,在体积不超过V的前提下,背包中物品的价值最大是多少?
看似多了一个参数增加了难度,实则不然——其实只是将0-1背包选择策略的默认的x1改为x k(0~n[i])。所以代码就很容易改出来了——
for(int i=1;i<=N;i++){
for(int v=0;v<=V;v++){
for(int k=0;k<=n[i];k++){
if(k*tj[i]<=v){
f[i][v]=max(f[i][v],f[i-1][v-k*tj[i]]+k*c[i]);
}
}
}
}
ans=f[N][V];
简单的背包问题及优化大致就是这样了,下面倾情奉献一道相关题目
=||ヽ( ̄▽ ̄)ノミ|Ю
【问题描述】
在《Harry Potter and the Deathly Hallows》中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品,现在给出该种物品的数量、体积、价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常地感谢你。
【输入格式】
第一行有2个整数,物品种数n和背包装载体积v。
第 2 行到 n+1 行每行3个整数,为第i种物品的数量m、体积w、价值s。.
【输出格式】
仅包含一个整数,即为能拿到的最大的物品价值总和。
【输入样例】
2 10
3 4 3
2 2 5
【输出样例】
13
【数据范围】
对于30%的数据:
1<=v<=500、1<=n<=2000、1<=m<=10、1<=w<=20、1<=s<=100
对于100%的数据:
1<=v<=500、1<=n<=2000、1<=m<=5000、1<=w<=20、1<=s<=100
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstring>
#include<cstdio>
using namespace std;
int f[2005][505]={0};
int n[2005],v[2005],p[2005];
int main(){
int N,C;
scanf("%d%d",&N,&C);
for(int i=1;i<=N;i++){
scanf("%d%d%d",&n[i],&v[i],&p[i]);
}
for(int i=1;i<=N;i++){
for(int c=0;c<=C;c++){
for(int k=0;k<=min(n[i],c/v[i]);k++){
f[i][c]=max(f[i][c],f[i-1][c-k*v[i]]+k*p[i]);
}
}
}
printf("%d",f[N][C]);
return 0;
}
[转载请标明出处 , 谢谢]