Problem Description
After months of hard working, Iserlohn finally wins awesome amount of scholarship. As a great zealot of sneakers, he decides to spend all his money on them in a sneaker store.
There are several brands of sneakers that Iserlohn wants to collect, such as Air Jordan and Nike Pro. And each brand has released various products. For the reason that Iserlohn is definitely a sneaker-mania, he desires to buy at least one product for each brand.
Although the fixed price of each product has been labeled, Iserlohn sets values for each of them based on his own tendency. With handsome but limited money, he wants to maximize the total value of the shoes he is going to buy. Obviously, as a collector, he won’t buy the same product twice.
Now, Iserlohn needs you to help him find the best solution of his problem, which means to maximize the total value of the products he can buy.
Input
Input contains multiple test cases. Each test case begins with three integers 1<=N<=100 representing the total number of products, 1 <= M<= 10000 the money Iserlohn gets, and 1<=K<=10 representing the sneaker brands. The following N lines each represents a product with three positive integers 1<=a<=k, b and c, 0<=b,c<100000, meaning the brand’s number it belongs, the labeled price, and the value of this product. Process to End Of File.
Output
For each test case, print an integer which is the maximum total value of the sneakers that Iserlohn purchases. Print "Impossible" if Iserlohn's demands can’t be satisfied.
Sample Input
5 10000 3
1 4 6
2 5 7
3 4 99
1 55 77
2 44 66
Sample Output
题意就是说有一个人有钱m他想要买些,这些鞋子有k种商标,每种商标的产品的价格为b,价值为c问如何买能使得获得的价值是最大的,注意这边是每种商标的商品至少买一件,和背包九讲里面分组背包有所不同,详情可以参考背包九讲,下面给出解释和代码:
/*
当前状态的来源有二:
A、当前品牌数目的前提之下获得的最大价值;
B、在比当前数目小的基础之上放一个另外品牌的商品所获得的最大价值;
所以我们就很容易就设计出状态转移方程:
f[j][v]= max(f[j][v], f[j][v-cost]+value);
f[j][v]= max(f[j][v], f[j-1][v-cost]+value);
f[j][v]表示为前j种商品放入体积为v获得的最大价值
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define max(a,b) a>b?a:b
int dp[15][10010];
int main()
{
int n,m,i,j,k,p,q,o,cnt[15],v[15][110],w[15][110];
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
memset(cnt,0,sizeof(cnt));
for(i=0;i<n;i++)
{
scanf("%d%d%d",&p,&q,&o);
v[p][cnt[p]]=o;
w[p][cnt[p]++]=q;
}
//初始化很奇妙,很有技巧
memset(dp,-1,sizeof(dp));//由于商品的价值可能是0,所以初始化不能为0
for(i=0;i<=m;i++)//表示的意思可以好好的理解
dp[0][i]=0;
for(i=1;i<=k;i++)
{
for(j=0;j<cnt[i];j++)//2 3 循环对调就成了每组最多选一件了 现在的循环是每组至少选一件 很神奇吧
{
for(p=m;p>=w[i][j];p--)
{
//如果分开写下面两条语句语句不能换,一旦换了当w[i][j]==0时会加2次
dp[i][p]=max(dp[i][p],dp[i][p-w[i][j]]+v[i][j]);
dp[i][p]=max(dp[i][p],dp[i-1][p-w[i][j]]+v[i][j]);
/*或者改成
dp[i][p]=max(dp[i][p],max(dp[i][p-w[i][j]]+v[i][j],dp[i-1][p-w[i][j]]+v[i][j]))
*/
}
}
}
if(dp[k][m]==-1)
printf("Impossible\n");
else
printf("%d\n",dp[k][m]);
}
return 0;
}