题目描述
给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,问如何选择装入背包的物品,使得装入背包的物品的总价值最大?
在选择装入背包的物品时,对每种物品i只能有两种选择,装入或者不装入,不能装入多次,也不能部分装入。
输入
第一行输入物品的个数n。
第二行输入物品的重量序列w。(中间有空格)
第三行输入物品的价值序列v。(中间有空格)
第四行输入背包容量c。
输出
第一行输出装入背包的物品。(用0和1表示,中间无空格)
第二行输出最大价值。
样例输入
3
3 4 5
4 5 6
10
样例输出
011
11
ac代码
#include <iostream>
#include <cstdio>
using namespace std;
int dp[1000][1000];
int w[1000], v[1000];
int a[1000];
int main(){
int m, c,i;
scanf("%d",&m);
for(int i = 1; i <= m; i++)
scanf("%d",&w[i]);
for(int i = 1; i <= m; i++)
scanf("%d",&v[i]);
scanf("%d",&c);
for(int i = 1; i <= m; i++){
for(int j = 0; j <= c; j++){
if(w[i]<=j) {
if(dp[i-1][j]>dp[i-1][j-w[i]]+v[i]) dp[i][j] = dp[i-1][j];
else dp[i][j] = dp[i-1][j-w[i]]+v[i];
}
else dp[i][j] = dp[i-1][j];
}
}
int b = c;
for(i = m; i >= 1; i--){
if(dp[i][b] > dp[i - 1][b]){
a[i] = 1;
b -= w[i];
}
}
for(i=1;i<=m;i++){
printf("%d",a[i]);
}
printf("\n");
printf("%d",dp[m][c]);
return 0;
}
关于输出每个物体的状态(拿/不拿):
因为在求dp[i][j]时,我们用dp[i-1][j]和dp[i-1][j-w[i]]+v[i]来求,所以可以反推选中的物品
for(i = m; i >= 1; i--){
if(dp[i][b] > dp[i - 1][b]){
a[i] = 1;
b -= w[i];
}
}
结合一张表格来理解
dp[6][12]=dp[5][12]说明6并未被选中,dp[3][12]>dp[2][12],说明3号被选中,那么接下来就应该比较dp[2][6]和dp[1][6]……
价值数组v = {8, 10, 6, 3, 7, 2}, 重量数组w = {4, 6, 2, 2, 5, 1},