题目
事情是这样的,jzk要去爬山,但是他的包容量有限,可是他需要非常多的能量,要不然就很容易饿。 第一行给出jzk准备爬几次山。 每次爬山都会带新的包(因为jzk每用一个包都会被zwg抢过去),和准备新的食物(因为每次剩下来的都被zwg吃了)。 下一行给你这一次食物的数目n,和背包容量k, 接下来的一行给出n个食物的能量,再一行给出n个食物的大小(占背包的容量)。 请帮助jzk计算他最多可以带多少能量的食物去爬山。输出可以携带食物的最大能量和。 (n,m<1000) 能量和食物均小于40000
输入
第一行包含整数T,表示有T组案例。
接着是T组案例,每组案例三行,第一行包含两个整数N,M,( N ≤ 1000 , M ≤ 1000 N\le1000,M\le1000 N≤1000,M≤1000),表示物品数量和袋子的体积。第二行包含表示每个物品能量的n个整数。第三行包含代表每个物品体积的n个整数。
输出
每组案例一行,只输出一个数字,表示jzk可以获得的最大能量。
样例输入
1
5 10
1 2 3 4 5
5 4 3 2 1
样例输出
14
题目分析
本题是很经典的01背包问题,对于这方面的问题也有很多解答,这里就说说我这个程序的一点基本思想以及处理的关键点。
处理01背包,主要是在分配价值与物体体积之间谋求最优解。在同等体积下,算出我们能够获得的最大价值,再利用已知的体积下的最大价值去完成对更大体积下的最大价值的更新。
比方说:对{物体体积,物体价值}={3,2},{2,3}。现有空间大小为5。
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
现在什么都没装入,因此在前n个大小的空间中价值均为0。现在取出物体1,装入。
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 0 | 2 | 2 | 2 |
可以发现,装入物体1之后,用3个空间装,价值为2,用5个空间装,价值同样为2.
那么我们在装入物体1的前提下再装入物体2。这个时候我们就会遇到一个问题,那就是:在物体1进入背包后,在剩余空间不够的情况下,我们如何处理物体2?
是将物体1取出后放入物体2,还是放弃放入物体2?
这个时候明显就出现了价值比较,对应的选择取决于选择后的价值。
v
a
l
u
e
[
i
]
=
{
m
a
x
(
v
a
l
u
e
[
i
]
,
v
a
l
u
e
[
i
−
v
o
l
u
m
n
[
k
]
]
+
w
[
k
]
)
i
f
i
≥
v
o
l
u
m
n
[
k
]
v
a
l
u
e
[
i
]
i
f
i
<
v
o
l
u
m
n
[
k
]
value[i]=\begin{cases} max(value[i],value[i-volumn[k]]+w[k]) &if&i\ge volumn[k]\\ value[i] &if &i<volumn[k] \end{cases}
value[i]={max(value[i],value[i−volumn[k]]+w[k])value[i]ififi≥volumn[k]i<volumn[k]
现在将物体2放入,得到value的数组
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
0 | 3 | 3 | 3 | 5 |
注意点:在向背包内放入物品时,需要由最大空间开始存放,直到放不下为止。原因是在进行价值比较时,我们是将当前状态下剩余空间下的最大价值加上放入物品价值后与当前状态比较,但是剩余空间下的最大价值中还没有放入该物品。
若是从小空间开始逐个尝试,则很有可能会造成一件物品放入了多次的情况。
代码
#include<iostream>
#include<cstring>
using namespace std;
int value[1005];//存储物体价值
int volumn[1005];//存储物体体积
int f[1005];//存储在该体积下的最大放入物体的价值
int n,m;
int main(){
int T;
cin >> T;
while(T--){
cin >> n >> m;
for(int i = 1;i<=n;++i) scanf("%d",&value[i]);
for(int i = 1;i<=n;++i) scanf("%d",&volumn[i]);
for(int i = 1;i<=n;++i){
for(int j = m;j>=0;--j){
if(volumn[i]<=j){
f[j]=max(f[j],f[j-volumn[i]]+value[i]);//价值比较
}
}
}
cout << f[m]<<endl;
memset(value,0,sizeof(value));
memset(volumn,0,sizeof(volumn));
memset(f,0,sizeof(f));
}
return 0;
}