题意:
输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。
Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
思路:
核心思想是对有限制的物品数目进行转化为01背包问题。
方式是:
用二进制把数目分解,分解之后的集合可以由里面的数组合成为1~原数目之间任何值。
HDU 2191
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
//freopen("in.txt","r",stdin);
int ncase;
cin>>ncase;
int dp[111],n,Limit,v[111],w[111],c[111];
int count,Value[1111],size[1111]; //转化之后的w和v
while(ncase--) {
count = 0;
cin>>Limit>>n;
for(int i = 0;i < n; i++) {
cin>>w[i]>>v[i]>>c[i];
for(int j = 1;j <= c[i]; j<<=1) {
Value[count] = j*v[i];
size[count++] = j*w[i];
c[i] -= j;
}
if(c[i]) { //注意要对这里进行补充
Value[count] = c[i]*v[i];
size[count++] = c[i]*w[i];
}
}
memset(dp,0,sizeof(dp));
for(int i = 0;i < count; i++) {
for(int j = Limit;j >= size[i]; j--) {
if(dp[j] < dp[j-size[i]]+Value[i])
dp[j] = dp[j-size[i]]+Value[i];
}
}
cout<<dp[Limit]<<endl;
}
return 0;
}