看起来很像分组背包,就是每一组的数量至少一,和最多一个又不一样,这里初始化无穷小。这题是看了别人的题解的。
状态转移方程:dp[i][j]表示进行到了第i组容量为j所装载的最大价值。
则dp[i][j]这个状态必须从dp[i-1][j-w[x]]+p[x] (选了第1个第i组的物品),dp[i][j-w[x]]+p[x](已经选过第i组的物品,这次又选了第i组的物品),dp[i][j](不选这个物品)
所以状态转移方程为:dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-w[x]]+p[x]));
代码
#include<stdio.h>
#include<string.h>
int dp[110][10010],a[110],b[110],c[110];
int Max(int a1,int b1)
{
return a1>b1?a1:b1;
}
int main()
{
int n,m,k;
int i,j,v;
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
for(i=0;i<=k+2;i++)
for(j=0;j<=m+2;j++)
dp[i][j]=-0x7f7f7f7f;
for(j=0;j<=m+2;j++) dp[0][j]=0;
for(i=1;i<=k;i++)
{
for(j=1;j<=n;j++)
{
if(a[j]==i)
{
for(v=m;v>=b[j];v--)
dp[i][v]=Max(Max(dp[i][v-b[j]]+c[j],dp[i][v]),dp[i-1][v-b[j]]+c[j]);
// 如果要写成把2个比较拆开来写的 请注意:
//下面两个顺序不能换,如果换了,当出现w[x]==0时,会加2次。
//dp[i][j]=max(dp[i][j],dp[i][j-w[x]]+p[x]);
//dp[i][j]=max(dp[i][j],dp[i-1][j-w[x]]+p[x]);
}
}
}
if(dp[k][m]<0) printf("Impossible\n");
else printf("%d\n",dp[k][m]);
}
return 0;
}