问题描述:小明今天很开心,因为在家买的新房子即将拿到钥匙。新房里面有一间他自己专用的、非常宽敞的房间。让他更高兴的是,他的母亲昨天对他说:“你的房间需要购买什么物品?怎么布置,你说了算,只要他们的价格总和不超过N元钱”。小明今天早上开始预算,但他想买太多的东西,肯定会超过母亲的N元限额。因此,他把对每件物品的渴望程度,分为5等级:用整数1->5表示,第5等表示最想要。他还从互联网上找到了每件商品(所有整数)的价格。他希望在不超过N元(可能等于N元)的情况下,将每件商品的价格与效益度的乘积的总和最大化.
设第j件物品的价格为p[j],重要度为w[j],其选中的k件商品,编号依次为j1,j2,……,jk,则所求的总和为:
p[j1]×w[j1]+p[j2]×w[j2]+ …+p[jk]×w[jk]。
请帮小明设计一个符合要求的购物清单。
其中N=2000,K=6
p[1]=200 w[1]=2
p[2]=300 w[2]=2
p[3]=600 w[3]=1
p[4]=400 w[4]=3
p[5]=1000 w[5]=4
p[6]=800 w[6]=5
参考书中的0-1背包问题的伪码编写:
#include <stdio.h>
#include <stdlib.h>
void Knapsack(int *v,int *w,int c,int n,int *m[] )
{ int jMax=(w[n]-1)<c?w[n]-1:c;
for(int j=0;j<=jMax;j++)
m[n][j]=0;
for(int j=w[n];j<=c;j++)
m[n][j]=v[n];
for(int i=n-1;i>1;i--){
jMax=(w[i]-1)<c?w[i]-1:c;
for(int j=0;j<=jMax;j++)
m[i][j]=m[i+1][j];
for(int j=w[i];j<=c;j++){
if(m[i+1][j]>(m[i+1][j-w[i]]+v[i])){
m[i][j]=m[i+1][j];
}
else
m[i][j]=m[i+1][j-w[i]]+v[i];
}
}
m[1][c]=m[2][c];
if(c>=w[1]){
m[1][c]=m[1][c]>(m[2][c-w[1]]+v[1])?m[1][c]:m[2][c-w[1]]+v[1];
}
}
void Traceback(int *m[],int *w,int c,int n,int *x)
{
for(int i=1;i<n;i++){
if(m[i][c]==m[i+1][c]){
x[i]=0;
}
else
{
x[i]=1;
c-=w[i];
}
}
x[n]=(m[n][c])?1:0;
}
int main (){
int n,k;int *p,*w,*q;
scanf("%d %d",&n,&k);
p=(int *)malloc((k+1)*sizeof(int));
w=(int *)malloc((k+1)*sizeof(int));
q=(int *)malloc((k+1)*sizeof(int));
for(int i=1;i<=k;i++){
scanf("%d %d",&p[i],&w[i]);
}
for(int i=1;i<=k;i++){
q[i]=p[i]*w[i];
}
int *m[n+1];
for(int i=0;i<=n;i++){
m[i]=(int *)malloc((n+1)*sizeof(int ));
}
Knapsack(q,p,n,k,m);
printf("%d \n",m[1][n]);
int *x;
x=(int *)malloc((n+1)*sizeof(int));
Traceback(m,p,n,k,x);
for(int i=1;i<=n;i++){
if(x[i]==1){
printf("%d ",i);
}
}
return 0;
}