题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3033
题目大意是:有n双鞋,分别属于k个品牌,然后有m的钱,每双鞋均有一个花费和价值,问用m的钱可以买到的最大价值是多少;
限制是每个品牌至少应买一种,且每种鞋子至多买一双;
就是分组的01背包问题;
定义f[k][j]为前i组用j的钱可以买到的最大价值,开始时令f的值均为非法状态,即赋为-1;但是f[0][j]要赋为0;因为这是起点;
然后f[k][j]=max(f[k][j],f[k-1][j-a[i].c]+a[i].w,f[k][j-a[i].c]+a[i].w);注意f[k][j-a[i].c]和f[k-1][j-a[i].c]至少有一个合法的才能够使得f[k][j]使用那个方程;
参考代码如下:
#include <iostream>
#include <cstring>
#define max(a,b) a>b?a:b
using namespace std;
int N,M,KM;
struct tt
{
int c;
int w;
}a[11][101];
int len[11];
int f[11][10001];
void execute()
{
int i,j,k;
memset(f,-1,sizeof(f));
memset(f[0],0,sizeof(f[0]));
for(k=1;k<=KM;k++)
{
for(i=1;i<=len[k];i++)
{
for(j=M;j>=a[k][i].c;--j)
{ //注意下面的两个if不能颠倒,否则会出错
if(f[k][j-a[k][i].c]>=0)
f[k][j]=max(f[k][j],f[k][j-a[k][i].c]+a[k][i].w);
if(f[k-1][j-a[k][i].c]>=0)
f[k][j]=max(f[k][j],f[k-1][j-a[k][i].c]+a[k][i].w);
}
}
}
int ans=-1;
for(i=0;i<=M;i++)
if(ans<f[KM][i])
ans=f[KM][i];
if(ans==-1)
cout<<"Impossible"<<endl;
else
cout<<ans<<endl;
}
int main()
{
int x, y, z;
while(cin>>N>>M>>KM)
{
memset(len,0,sizeof(len));
for(int i=0;i<N;i++)
{
cin>>x>>y>>z;
len[x]++;
a[x][len[x]].c=y;
a[x][len[x]].w=z;
}
execute();
}
return 0;
}