有N中物品和一个容量为V的背包,每种物品都有无限件可用,放入第i中物品所占的空间是ci,价值是wi,求解将哪些物品放入背包中可使这些物品的耗费空间总和不超过背包的容量,且价值总和最大。
for(i=1;i<=n;i++)
for(v=ci;v<=V;v++)
f[v]=max(f[v],f[v-ci]+wi);
在01背包中让v递减循环为了保证第i次循环中的状态f[i,v]是由状态f[i-1,v-ci]递推而来,换句话说是为了保证每件物品只选一次。保证在考虑选入第i件物品这件策略是,依据的是一个绝无已经选入第i件物品的子结果f[i-1,v-ci]。而完全背包的特点是每种物品可选无限次,所以在考虑加选一件第i种物品时,正需要一个可能已选入第i种物品的子结果f[i,v-ci],所以必须采用v递增的顺序循环。
采用二维数组表示即为:
f[i][v]=max(f[i-1][v],f[i][v-ci]+wi);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<queue>
#define maxn 30010
using namespace std;
int dp[maxn];
int a[5];
int main()
{
int t,n;
a[1]=150;
a[2]=200;
a[3]=350;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i=1;i<=3;i++)
{
for(int j=a[i];j<=n;j++)
{
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
}
printf("%d\n",n-dp[n]);
}
return 0;
}