注解
1、本题属于多重背包。关键代码如下:第一句是找当前所剩余的钱能买到的最大数目与该种粮食所剩数目的最小值。第二步的k从1到maxnum,就是分别找买1件,买2件,…,买maxnum件该种粮食的情况,对于每种情况,从钱数为n到钱数为money[j](必须倒序)均可买该种粮食,买了之后的最大值就是max(dp[s], dp[s-money[j]+weight[j])。
for(int j=0; j<m; j++){
int maxnum = min(num[j], n/money[j]);
for(int k=1; k<=maxnum; k++){
for(int s=n; s>=money[j]; s--){
dp[s] = max(dp[s], dp[s-money[j]]+weight[j]);
}
}
}
代码
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 100 + 10;
int money[maxn];
int weight[maxn];
int num[maxn];
int dp[maxn];
int main() {
int C;
cin>>C;
for(int i=0; i<C; i++){
int n;
int m;
cin>>n>>m;
for(int j=0; j<m; j++){
cin>>money[j]>>weight[j]>>num[j];
}
memset(dp, 0, sizeof(dp));
for(int j=0; j<m; j++){
int maxnum = min(num[j], n/money[j]);
for(int k=1; k<=maxnum; k++){
for(int s=n; s>=money[j]; s--){
dp[s] = max(dp[s], dp[s-money[j]]+weight[j]);
}
}
}
cout<<dp[n]<<endl;
}
return 0;
}