问题描述:
现在给你一个容量为V的背包,有N个物品,其中第i件物品的重量为wi,价值为vi,第i件物品一共有si件,问在有限的容量内,最多可以拿到多少价值的物品。
题目分析:
仔细一看,多重背包问题和完全背包问题的差距就在物品的个数上,完全背包问题是同一类物品有无数件,但多重背包不让着你,多重背包给你规定了最多件数。仔细看看还挺有意思,01背包是要么0件要么1件,多重背包是要么可以选0~si件,而完全背包则是可以选0~∞件。
那我们拓展一下思维,这是规定了同类物品最多能拿的个数,要是规定了第i类物品最少要拿多少件呢?很容易想到,只需要初始化的时候提前拿一些,就转换成了01背包问题咯(题外话题外话)
回归正题,多重背包问题就是在完全背包问题加了一个限制条件,“最多能拿si件”。那我们只需要改一改完全背包问题的代码,不就迎刃而解了吗?
假设取前i件物品装入容量为V的背包,第i件物品拿k件所得到的最大值为dp[i][j]
那么dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i])这里的k的范围是:0≤k≤s[i]
于是代码如下...
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=1e3+7;
int w[MAXN],N,V,v[MAXN],dp[MAXN][MAXN],s[MAXN];
int main()
{
memset(dp,0,sizeof(dp));
cin>>V>>N;
for(int i=1;i<=N;i++)
{
cin>>w[i]>>v[i]>>s[i];
}
for(int i=1;i<=N;i++)
{
for(int j=0;j<=V;j++)
{
for(int k=0;k<=s[i]&&k*w[i]<=j;k++)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
}
}
}
cout<<dp[N][V]<<endl;
return 0;
}//二维
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=1e3+7;
int w[MAXN],N,V,v[MAXN],dp[MAXN],s[MAXN];
int main()
{
memset(dp,0,sizeof(dp));
cin>>V>>N;
for(int i=1;i<=N;i++)
{
cin>>w[i]>>v[i]>>s[i];
}
for(int i=1;i<=N;i++)
{
for(int j=V;j>=0;j--)
{
for(int k=0;k<=s[i]&&k*w[i]<=j;k++)
{
dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);
}
}
}
cout<<dp[V]<<endl;
return 0;
}//一维