问题
给定n种物品和一背包
wi :物品i的重量
vi :物品i的重量价值
C:背包的容量
问:应如何选择装入背包的物品, 使得装入背包中物品的总价值最大?
分析
p[i][j]代表可选择物品为前i个,背包容量为j时的最大价值
当j<w[i]时说明无法装入第i个物体,此时去掉第i个物品并无影响所以p[i][j]=p[i-1][j]
当j>=w[i]时我们需要判断v[i]+p[i-1][j-w[i]]与p[i-1][j]的大小来对p[i][j]进行赋值
为什么是判断v[i]+p[i-1][j-w[i]]与p[i-1][j]呢
当j>w[i]时,我们可以装入i,价值为v[i],此时容量为j-w[i],且物品到了第i-1个物品,所以p[i][j]可以为v[i]+p[i-1][j-w[i]]
同样,我们也可以不装入此物品,那么此时去掉这个物品并没有影响,就有p[i][j]=p[i-1][j]
由于p[i][j]代表背包容量为j时的最大价值,所以需要比较两种情况的最大值,并填入p[i][j]
用数组s[i][j]记录在容量为j的情况下是否选择第i个物品
代码实现
#include<stdio.h>
#define N 100
int w[N],v[N],p[N][N],s[N][N];//p为最大价值,s为选择与否
void print(int n,int m,int s[][N]){
if(n<1) return ;
if(s[n][m]==1){
print(n-1,m-w[n],s);
printf("%d ",n);
}else{
print(n-1,m,s);
}
}
int main(){
int n,m,i,j,k;
printf("请输入物品种类数目和背包大小:");
scanf("%d %d",&n,&m);
printf("请输入各物品所占体积:");
for(i=1;i<=n;i++){
scanf("%d",&w[i]);
}
printf("请输入各物品的价值:");
for(i=1;i<=n;i++){
scanf("%d",&v[i]);
}
for(i=0;i<=n;i++){//初始化第零列
p[i][0]=0;
s[i][0]=0;
}
for(i=0;i<=m;i++){//初始化第零行
p[0][i]=0;
}
for(i=1;i<=n;i++){//选择前i个物品
for(j=1;j<=m;j++){//增大容量
if(w[i]>j){//物品不能装入
p[i][j]=p[i-1][j];
s[i][j]=0;
}
else{//可装入时分情况
if(v[i]+p[i-1][j-w[i]]>p[i-1][j]){//比较选与不选的价值大小,取大的
p[i][j]=v[i]+p[i-1][j-w[i]];
s[i][j]=1;//选择后为1
}else{
p[i][j]=p[i-1][j];
s[i][j]=0;//不选为0
}
}
}
}
printf("最大价值为:%d\n选择的物品为:",p[n][m]);
print(n,m,s);
return 0;
}