I love sneakers!

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 626 Accepted Submission(s): 239

 

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.



hdu   3033     I love sneakers!_分组背包


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 31 4 62 5 73 4 991 55 772 44 66




 

Sample Output




255




 

 

Source



2009 Multi-University Training Contest 13 - Host by HIT



 第一眼看到题目,,我知道是背包问题,但是想了一下后,发现自己不会做,,因为那个每组至少取一个不知道如何处理,,马上看了下题解,才发现是一个陌生的题型,,分组背包,快速学了一下,然后就过了



题意:给定N个物品,,分成m组,每个物品都有价值vi和花费(重量)costi,现在要求每组至少拿一个,则在总共花费不超过money的情况下,求最大价值



题型:0-1分组背包



 dp[i][j]表示在扫到第i组时剩余钱j的情况下,所能得到的最大价值, 不过dp数组的初始化要尤其注意,不能初始化为0



因为可能存在物品花费costi=0的情况,如果初始化为0,就无法确定该件物品到底拿没拿,,(其实也没想懂,过段时间再看看)



dp[i][j]=max(dp[i][j],dp[i-1][j-cost[i]+val[i]],dp[i][j-cost[i]]+val[i])



这三种情况分别对应于不取该物品,在第i组中第一次取该物品,在第i组中非第一次取该物品



分组背包初始化和循环次序还要好好琢磨

#include<iostream>
 #include<cstdio>
 #include<cstring>
 using namespace std;
 int max(int a,int b,int c)
 {
     if(a>b)
         b=a;
     return b>c?b:c;
 }
 int dp[11][10001],flag[100001],val[100001],cost[100001];
 int main()
 {
     int num,mey,bra;
     while(~scanf("%d %d %d",&num,&mey,&bra))
     {
         for(int i=1;i<=num;i++)
             cin>>flag[i]>>cost[i]>>val[i];
         memset(dp,0,sizeof(dp));
         for(int i=0;i<=mey;i++)
             dp[0][i]=0;//初始化为-1的情况下,记得将第0组值初始化为0
         for(int i=1;i<=bra;i++)
         for(int j=1;j<=num;j++)        
              if(flag[j]==i)  //一组一组的取
             for(int m=mey;m>=cost[j];m--)       //   m和j的循环不要弄错了,,,否则无法保证最多????这个地方也不是                                                               //很懂过段时间看看
        dp[i][m]=max(dp[i][m],   
             dp[i][m-cost[j]]+val[j],dp[i-1][m-cost[j]]+val[j]);
        if(dp[bra][mey]<0)
            cout<<"Impossible"<<endl;
        else
            cout<<dp[bra][mey]<<endl;
    }
    return 0;
}