根据背包9讲:
费用加了一维,只需状态也加一维即可。设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值。状态转移方程就是:
f[i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}
如前述方法,可以只使用二维的数组:当每件物品只可以取一次时变量v和u采用逆序的循环,当物品有如完全背包问题时采用顺序的循环。当物品有如多重背包问题时拆分物品。
这题在N中刚好选M个,初始化时只要1...m初始化为负无穷大 就能保证刚好取那么多,这在背包9讲中也有讲,求最大值初始化为负无穷,求最小值初始化为正无穷。
#include<stdio.h>
#include<string.h>
#define inf -10000
int f[110][1100];
struct node
{
int time;
int value;
}a[110];
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,l;
scanf("%d%d%d",&n,&m,&l);
int i,j,k;
memset(f,0,sizeof(f));
for(i=1;i<=m;i++)
{
for(j=0;j<=l;j++)
{
f[i][j]=inf;
}
}
for(i=1;i<=n;i++)
{
scanf("%d%d",&a[i].time,&a[i].value);
}
for(i=1;i<=n;i++)
{
for(k=m;k>=1;k--)
{
for(j=l;j>=a[i].time;j--)
{
if(f[k-1][j-a[i].time]!=inf)
f[k][j]=max(f[k][j],f[k-1][j-a[i].time]+a[i].value);
}
}
}
if(f[m][l]==inf)
printf("0\n");
else
printf("%d\n",f[m][l]);
}
return 0;
}