【理解】
容量为M的背包,和N种物品。每种物品都有三个属性,vi,wi,与ci,分别表示这种物品的体积、价值和件数。
从这些所给物品中,选出若干件,其体积之和不能超过背包容量,并且使所选物品的权值的和最大
我们先分析题目,它给出了物品的三个属性,并且要求就是体积不超过背包容量,并且最终权值和最大,我们这时
就可以想到使用多重背包算法。
【实现】
我们可以先从背包容量最大的开始直到背包容量为1,因为这样子可以减少空间复杂度。为什么呢?f[j - vi[i] * k] + wi[i] * k
表示计算上一个的总价值再加上现在现在的价值 与 上一个包容量计算的价值进行对比选择最大值,这样直接就大大减少了空间的浪费
且数组只需要开1维。
【具体】
根据方程
f[j] = max(f[j], f[j - vi[i] * k] + wi[i] * k);//比较上一个价值与当前计算价值数
我们就可以选择出目标背包容量内的最大价值数,然后进行判断最大数更新
【总结】
依然的,动态规划的特点就是解决了重复运算的问题,同时我们选择倒序的方法也解决了开二维数组而导致空间复杂度增加的问题
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define maxe 510
unsigned int m, n;
unsigned int f[maxe] = {};
unsigned int vi[maxe] = {}, wi[maxe] = {}, ci[maxe] = {};
unsigned int ma(unsigned int n, unsigned int m) { return n > m ? n : m; }
/*
以下是具体实现
*/
//v体积 w价值 c件数,求最大权值和
int main() {
cin >> m >> n;
for (unsigned int i = 1; i <= m; i++) {
cin >> vi[i] >> wi[i] >> ci[i];
}
unsigned int maxem = 0;//保存最大值
for (unsigned int i = 1; i <= m; i++) {// m(物品数)>=i>=1
for (unsigned int j = n; j >= 1; j--) {//j:当前包容量 j - vi[i] * k=单个总容量
if (j - vi[i] >= 0) {
for (unsigned int k = 1; k <= ci[i]; k++) {//k=1-ci[i] 当前件数
if (j >= vi[i] * k)//判断体积是否超出限制
f[j] = ma(f[j], f[j - vi[i] * k] + wi[i] * k);//比较上一个价值与当前计算价值数
if (f[j] > maxem)
maxem = f[j];//更新最大数
}
}
else
break;
}
}
cout << maxem;
return 0;
}