有 N 件物品 d1,......dN,每件物品重量为 W1,..., WN
(Wi > 0), 每件物品价值为 V1,......VN (Vi>0)。用这N件物品的某个子集
填空背包,使得所取物品的总重量<=TOTAL,并设法使得背包中物品的价值尽可
能高。
19.解答:
#include<stdio.h>
#define MAX_N 10
#define MAX_WEIGHT 20
#define MAX_VALUE 20
void bag(const int Weight[], const int Value[], const int n, const int TotalWeight)
{
int ValueReached[MAX_VALUE*MAX_N+1] = {0};
int WeightUsed[MAX_VALUE*MAX_N+1];
int LastUseIndex[MAX_VALUE*MAX_N+1];
int i,j;
const int INF = 10000000;
for(i=0; i<=MAX_VALUE*MAX_N; ++i)
WeightUsed[i] = INF;
ValueReached[0] = 1; // 记录价值为i是否可达到
WeightUsed[0] = 0; // 记录达到价值i时使用的重量
LastUseIndex[0] = -1; // 记录达到价值i所使用物品的最后一个的下标
for(i=0; i<n; ++i)
{
int w = Weight[i];
int v = Value[i];
for(j=MAX_VALUE*MAX_N-v; j>=0; --j)
{
if( !ValueReached[j] )
continue;
if( WeightUsed[j]+w > TotalWeight )
continue;
if( (!ValueReached[j+v]) || (WeightUsed[j+v]>WeightUsed[j]+w) )
{
ValueReached[j+v] = 1;
LastUseIndex[j+v] = i;
WeightUsed[j+v] = WeightUsed[j] + w;
}
}
}
for(i=MAX_VALUE*MAX_N; /*i>=0*/; --i)
if(ValueReached[i])
break;
printf("可装入物品总价值为%d/n", i);
printf("装入了以下物品:/n");
// 注意:输出的顺序是“反”的,如果要“正”的,需另外处理
j=LastUseIndex[i];
while( j != -1 )
{
printf("第%d件/t", j+1);
i -= Value[j];
j = LastUseIndex[i];
}
printf("/n");
}
int main(void)
{
int i;
int TotalWeight,n;
int w[MAX_N], v[MAX_N];
printf("输入背包可承受的最大重量:/n");
scanf("%d", &TotalWeight);
printf("输入物品的件数:/n");
scanf("%d", &n);
for(i=0; i<n; ++i)
{
printf("输入第%d件物品的重量:/n", i+1);
scanf("%d", w+i);
printf("输入第%d件物品的价值:/n", i+1);
scanf("%d", v+i);
}
bag(w, v, n, TotalWeight);
return 0;
}