题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191
题目很容易理解。
关于背包问题可以看dd enginer的《背包九讲》,链接:https://github.com/tianyicui/pack
这篇博客则用图片把背包问题讲的非常明了,同时讲了二进制优化多重背包问题,链接:http://blog.csdn.net/lyhvoyage/article/details/8545852
以下为没有经过二进制优化的代码:
#include <iostream>
using namespace std;
int nCases;
int nValue, nKind;
int value[105], weight[105], bag[105];
int nMultiplePack[105];
int main()
{
//freopen("input.txt", "r", stdin);
scanf("%d", &nCases);
while(nCases--)
{
memset(nMultiplePack, 0, sizeof(nMultiplePack));
scanf("%d %d", &nValue, &nKind);
for(int i=0; i<nKind; ++i)
scanf("%d %d %d", &value[i], &weight[i], &bag[i]);
for(int i=0; i<nKind; ++i)
for(int j=0; j<bag[i]; ++j)
for(int k=nValue; k>=value[i]; --k)
if(nMultiplePack[k] < nMultiplePack[k-value[i]]+weight[i])
nMultiplePack[k] = nMultiplePack[k-value[i]] + weight[i];
printf("%d\n", nMultiplePack[nValue]);
}
return 0;
}
以下为经过二进制优化的版本:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int nCase,Limit,nKind,i,j,v[111],w[111],c[111],dp[111];
//v[]存价值,w[]存尺寸,c[]存件数
//在本题中,价值是米的重量,尺寸是米的价格
int count,Value[1111],size[1111];
//count存储分解完后的物品总数
//Value存储分解完后每件物品的价值
//size存储分解完后每件物品的尺寸
cin>>nCase;
while(nCase--)
{
count=0;
cin>>Limit>>nKind;
for(i=0; i<nKind; i++)
{
cin>>w[i]>>v[i]>>c[i];
//对该种类的c[i]件物品进行二进制分解
for(j=1; j<=c[i]; j<<=1)
{
//<<右移1位,相当于乘2
Value[count]=j*v[i];
size[count++]=j*w[i];
c[i]-=j;
}
if(c[i]>0)
{
Value[count]=c[i]*v[i];
size[count++]=c[i]*w[i];
}
}
//经过上面对每一种物品的分解,
//现在Value[]存的就是分解后的物品价值
//size[]存的就是分解后的物品尺寸
//count就相当于原来的n
//下面就直接用01背包算法来解
memset(dp,0,sizeof(dp));
for(i=0; i<count; i++)
for(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;
}