题意:有n种品牌的鞋子啊,每种品牌又分几类不同的鞋子。已知每双鞋子的标价和实际的价值。
要求每种品牌至少买一类鞋子。问花m钱能买的鞋子的最大价值。如果不能满足每种品牌至少
买一双鞋子(就是钱不够用啦)就输出不可能。
分析:
《背包九讲》中的分组背包是每组最多选一个。而这题是每组要至少选一个。
dp[i][k-v[j]]+w[j]表示不是第一次在本组中选鞋子。
dp[i-1][k-v[j]]+w[j]表示是第一次在本组中选,所以应该由上一组选择递推过来。
dp[i][j]表示前i中brand 用了j这么多的钱得到的价值。。。
初始化为负数。。。表示不能达到的状态(钱不够用)
另外dp[0][j]初始化为0,因为在第一类里选第一个时,如果钱够用是直接加上价值(初始量为0)。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 0x3f3f3f3f using namespace std; int bnum,mon,tot; int dp[15][10005]; int brand[105],w[105],v[105]; int maxx(int a,int b,int c) { int t=a>b?a:b; return t>c?t:c; } void init() { for(int i=0;i<=bnum;i++) { for(int j=0;j<=mon;j++) { if(i==0) dp[i][j]=0; else dp[i][j]=-INF; } } } void solve() { int i,j,k; for(i=1;i<=bnum;i++) { for(j=1;j<=tot;j++) { if(brand[j]==i) { for(k=mon;k>=v[j];k--) { dp[i][k]=maxx(dp[i][k],dp[i][k-v[j]]+w[j],dp[i-1][k-v[j]]+w[j]); } } } } } int main() { while(scanf("%d%d%d",&tot,&mon,&bnum)!=EOF) { for(int i=1;i<=tot;i++) scanf("%d%d%d",&brand[i],&v[i],&w[i]); init(); solve(); if(dp[bnum][mon]<0) printf("Impossible\n"); else printf("%d\n",dp[bnum][mon]); } return 0; }