说完了01背包,完全背包,我们接着学习多重背包,还是介绍下问题
题目
有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
我们还是老样子,先写出多重背包的类似于01背包的状态转移方程
dp[i][v] = max(dp[i-1][v],dp[i-1][v - k*c[i]]+k*w[i]); 0<=k<=c[i];
我们还是要根据二进制的思想,每一种物品呢,我们分成若干件
int n; //输入有多少种物品
int c; //每种物品有多少件
int v; //每种物品的价值
int s; //每种物品的尺寸
int count = 0; //分解后可得到多少种物品
int value[MAX]; //用来保存分解后的物品价值
int size[MAX]; //用来保存分解后物品体积
scanf("%d", &n); //先输入有多少种物品,接下来对每种物品进行分解
while (n--) //接下来输入n中这个物品
{
scanf("%d%d%d", &c, &s, &v); //输入每种物品的数目和价值
for (int k=1; k<=c; k<<=1) //<<右移 相当于乘二
{
value[count] = k*v;
size[count++] = k*s;
c -= k;
}
if (c > 0)
{
value[count] = c*v;
size[count++] = c*s;
}
}
这样呢,我们再根据01背包的公式,写出状态转移
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<set>
#include<algorithm>
#include<cmath>
#define ll __int64
#define MAX 1000009
using namespace std;
int c[MAX];//件数
int w[MAX];//尺寸
int v[MAX];//价值
int dp[MAX];
int Count;//分解完的物品总数
int Value[MAX];//分解完的每件物品的价值
int Size[MAX];//分解完每件物品的体积
int main()
{
int t;
int kind,Limit;//种类,背包最容积
cin>>t;
while(t--)
{
cin>>Limit>>kind;
Count = 0;
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];
Count++;
c[i]-=j;
}
if(c[i]>0)
{
Value[Count] = c[i]*v[i];
Size[Count] = c[i]*w[i];
Count++;
}
}
memset(dp,0,sizeof(dp));//转化成01背包
for(int i = 0;i<Count;i++)这里循环用的是Count而不是n
{
for(int j = Limit;j>=Size[i];j--)
{
dp[j] = max(dp[j],dp[j-Size[i]]+Value[i]);
}
}
cout<<dp[Limit]<<endl;
}
return 0;
}

被折叠的 条评论
为什么被折叠?



