一、题目链接:悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
1.题目分析:这实际上是个多重背包问题,将每种大米按两种情况进行讨论
1):如果第 i 种大米:价格*袋数>=经费,将它按完全背包计算。
2):如果第 i 种大米:价格*袋数 < 经费,将它转换为0-1 背包计算(按二进制转换,1、2、4...降低时间复杂度)
2.AC代码:
#include<bits/stdc++.h>
using namespace std;
#define max(a,b) (a>b)?(a):(b)
#define N 105
int f[N];
int i,j,n,m;
int cost[N],value[N],amount[N];
void ZeroOnePack(int cost,int value) { //0-1背包
for(j=n;j>=cost;j--)
f[j]=max(f[j],f[j-cost]+value);
}
void CompletePack(int cost,int value) { //完全背包
for(j=cost;j<=n;j++)
f[j]=max(f[j],f[j-cost]+value);
}
void MultiplePack(int cost,int value,int amount){ //多重背包
if(n<=cost*amount){
CompletePack(cost,value);
return;
}
int intenger=1;
while(intenger<amount){
ZeroOnePack(intenger*cost,intenger*value);
amount-=intenger;
intenger*=2;
}
ZeroOnePack(amount*cost,amount*value);
}
void solve() {
cin >> n >> m;
memset(f,0,sizeof(f));
for(i=1;i<=m;i++){
cin >> cost[i] >> value[i] >> amount[i];
MultiplePack(cost[i],value[i],amount[i]);
}
cout << f[n] << endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int tcas; cin >> tcas;
for(int cas=0;cas<tcas;cas++) solve();
return 0;
}