一道多重背包的裸题,想看详解的可以看这篇博客传送门(Coins)
AC代码:
#include <iostream>
#include <cstring>
#define MAX(a,b) a>b?a:b
#define MAXN 100000
#define INF 0x3f3f3f3f
using namespace std;
int dp[MAXN];
int val[205];
int w[205];
int num[205];
int T,n,m;
void CompletePack(int val,int w){
for(int i=val;i<=n;i++){
dp[i] = MAX(dp[i],dp[i-val] + w);
}
}
void ZeroPack(int val,int w){
for(int i=n;i>=val;i--){
dp[i] = MAX(dp[i],dp[i-val]+w);
}
}
void MutiplePack(int val,int w,int num){
if(val * num > n){
CompletePack(val,w);
}
else {
int k = 1;
while(k<=num){
ZeroPack(k*val,k*w);
num -= k;
k *= 2;
}
ZeroPack(num*val,num*w);
}
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d%d",&val[i],&w[i],&num[i]);
}
memset(dp,-INF,sizeof(dp));
dp[0] = 0;
for(int i=0;i<m;i++){
MutiplePack(val[i],w[i],num[i]);
}
printf("%d\n",dp[n]);
}
return 0;
}
/***
[来源] HDU 2191
[题目] 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
[大意]
很好看懂,多重背包裸题。多重背包有注释的代码可以看Coins这题。
[输入]
1
8 2
2 100 4
4 100 2
[输出]
400
*/