#include<iostream>
#include<string.h>
using namespace std;
int C,n,m,p[200],h[200],c[200];
int dp[200];
int main()
{
cin>>C;
while(C--)
{
cin>>n>>m;//n是背包大小,m是物品数量
int total=n;
memset(dp,0,sizeof(dp));
for(int i = 1;i <= m; i++)
{
cin>>p[i]>>h[i]>>c[i];//p是物品占背包大小,h是物品价值,c是物品的数量
}
for(int i = 1;i <= m; i++ )
{
if(p[i]*c[i]>n)//如果物品数量*物品占背包大小大于背包总大小,相当于完全背包,套用完全背包模板
{
for(int j = p[i];j <=n ;j++)//完全背包
{
dp[j]=max(dp[j],dp[j-p[i]]+h[i]);
}
}
else{//否则执行下面算法,将这个物品的(1,2,4,...,2的n次方)倍当做一个物品分别跑01背包,
//最后再跑一遍跑p[i]*c[i]的01背包,
int k=1;
while(k<c[i])
{
for(int j = n;j >=p[i]*k ;j--)//01背包
{
dp[j]=max(dp[j],dp[j-p[i]*k]+h[i]*k);
}
c[i]-=k;
k*=2;
}
for(int j=n;j>=p[i]*c[i];j--)//01背包
{
dp[j]=max(dp[j],dp[j-p[i]*c[i]]+h[i]*c[i]);
}
}
}
for(int i=1;i<=n;i++)
{
cout<<dp[i]<<" ";
}
cout<<endl;
cout<<dp[n]<<endl;
}
return 0;
}
/*
3
10 3
1 100 1
3 400 2
5 500 1
10 3
1 100 4
3 400 2
5 500 1
结果是:
1000
1200
*/
封装后的代码为
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N = 1005;
int dp[N];
int c[N],w[N],num[N];
int n,m;
void ZeroOne_Pack(int cost,int weight,int n)
{
for(int i=n; i>=cost; i--)
dp[i] = max(dp[i],dp[i-cost] + weight);
}
void Complete_Pack(int cost,int weight,int n)
{
for(int i=cost; i<=n; i++)
dp[i] = max(dp[i],dp[i-cost] + weight);
}
int Multi_Pack(int c[],int w[],int num[],int n,int m)
{
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++)
{
if(num[i]*c[i] > m)
Complete_Pack(c[i],w[i],m);
else
{
int k = 1;
while(k < num[i])
{
ZeroOne_Pack(k*c[i],k*w[i],m);
num[i] -= k;
k <<= 1;
}
ZeroOne_Pack(num[i]*c[i],num[i]*w[i],m);
}
}
return dp[m];
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>m>>n;
for(int i=1; i<=n; i++)
cin>>c[i]>>w[i]>>num[i];
cout<<Multi_Pack(c,w,num,n,m)<<endl;
}
return 0;
}