TOJ礼品兑换 (多重背包恰好装满)

近期crq老师为了提高各个学生对ACM的兴趣,在TOJ上增加了积分制度和礼品兑换功能, TOJ的积分是来之不易的,固然同学们都想用同一积分换取最大价值的礼品,某同学用了M的积分换取了一些礼品。 请问:他用M的积分最多能换取多少价值的礼品呢? (积分M一定要使用完)

输入

输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数M和N(1<=M<=1000,1<=N<=100),分别表示换取的总积分和礼品的种类,然后是N行数据,每行包含3个数p,h和c(1<=p<=100,0<=h<=200,1<=c<=1000),分别表示每种礼品的价格、对应种类礼品的剩余数目以及每类礼品的消耗的积分。

输出

对于每组测试数据,如果M能使用完请输出"The maximum value is X." ,否则输出"This is impossible.".你可以假设同一类物品能多次换取。每个实例的输出占一行。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int t,n,m;
 4 int f[1005];
 5 const int INF=0x3f3f3f3f;
 6 struct Node{
 7     int w,v;
 8 };
 9 vector<Node> vec;
10 int main()
11 {
12     ios::sync_with_stdio(false);
13     cin>>t;
14     while(t--){
15         vec.clear();
16         for(int i=1;i<=1004;i++) f[i]=-INF;
17         f[0]=0;
18         cin>>n>>m;
19         for(int i=1,p,h,c;i<=m;i++){
20             cin>>p>>h>>c;
21             int sum=0;
22             for(int j=1;j<=h;j*=2){
23                 h-=j;
24                 vec.push_back({j*p,c*j});
25             }
26             if(h>0)
27                 vec.push_back({h*p,h*c});
28         }
29         for(auto X:vec){
30             for(int i=n;i>=X.v;i--){
31                 if(f[i-X.v]!=-INF)
32                     f[i]=max(f[i],f[i-X.v]+X.w);
33             }
34         }
35         if(f[n]==-INF) cout << "This is impossible." << endl;
36         else{
37             cout << "The maximum value is ";
38             cout << f[n] << "." << endl;
39         }
40     }
41     return 0;
42 }
View Code

样例输入

样例输出

解题思路:多重背包恰好装满

原文地址:https://www.cnblogs.com/qq-1585047819/p/10888528.html