题意:给定m种物品,每种物品有价格,重量,数量。你有n元钱,求用这n元钱能买到的最多的重量。
思路:非常明显的多重背包裸题。这样的题目应该在2分钟之内打出来,因为就是01背包+2进制优化。
这里的二进制思想非常精妙,假设一种物品有7个,那么将其分成1,2,4这三种不同数量的物品,在这三种里面随便选(每种可以选或不选)-----01背包思路。因为(1,2,4可以组成1到7之间的任意一个数)。
反思:通过这题,我加深了对二进制思想的理解,又重新思考了01背包的状态转移过程。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+9;
int dp[maxn];
struct Point
{
int p,h,c;
}p[500];
int n,m;
int v[500],w[500];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int cnt=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&p[i].p,&p[i].h,&p[i].c);
for(int j=1;j<=p[i].c;j*=2)
{
v[cnt]=j*p[i].p;
w[cnt]=j*p[i].h;
p[i].c-=j;
cnt++;
}
if(p[i].c>0)
{
v[cnt]=p[i].c*p[i].p;
w[cnt]=p[i].c*p[i].h;
cnt++;
}
}
memset(dp,0,sizeof(dp));
int ans=0;
for(int i=0;i<cnt;i++)
{
for(int j=n;j>=v[i];j--)
{
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
//ans=max(ans,dp[j]);
}
}
printf("%d\n",dp[n]);
}
return 0;
}