题目链接:http://http://acm.hdu.edu.cn/showproblem.php?pid=3033
题意:
n组数据,m元钱,k种小吃
每组数据包含a,b,c a:小吃种类 b:小吃价格 c:小吃价值
每种小吃买至少有1个
如果不能达到要求,就输出Impossible
否则就输出小吃的最大价值
思路:
这不是明显的分组背包,需要自己去变形
将同一种类的小吃归到一起
dp[ i ][ x ]代表第i种小吃容量为x的价值
转移方程就是:
dp[i][x] = max(dp[i][x],dp[i][x-p[i][j].w]+p[i][j].v)
dp[i][x] = max(dp[i][x],dp[i-1][x-p[i][j].w]+p[i][j].v)
这两个的位置不能换
当i=1,p[ i ][ j ].w=0时
如果调换顺序
dp[ i ][ x ]会被加了两次
导致答案出错,wa了好几把,就是这里错了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
int num[15];
struct node
{
int v,w;
}p[15][105];
int dp[15][10005];
int main()
{
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(p,0,sizeof(p));
memset(num,0,sizeof(num));
int a,b,c;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
p[a][num[a]].w=b;//变形为典型的分组背包形式
p[a][num[a]].v=c;
num[a]++;
}
memset(dp,-1,sizeof(dp));
memset(dp[0],0,sizeof(dp[0]));
for(int i=1;i<=k;i++)
{
for(int j=0;j<num[i];j++)
{
for(int x=m;x>=p[i][j].w;x--)
{
dp[i][x] = max(dp[i][x],dp[i][x-p[i][j].w]+p[i][j].v);
dp[i][x] = max(dp[i][x],dp[i-1][x-p[i][j].w]+p[i][j].v);
}
}
}
if(dp[k][m]==-1)
{
printf("Impossible\n");
continue;
}
printf("%d\n",dp[k][m]);
}
return 0;
}