【理解】
容量為M的背包,和N種物品。每種物品都有三個(gè)屬性,vi,wi,與ci,分別表示這種物品的體積、價(jià)值和件數(shù)。
從這些所給物品中,選出若干件,其體積之和不能超過(guò)背包容量,并且使所選物品的權(quán)值的和最大
我們先分析題目,它給出了物品的三個(gè)屬性,并且要求就是體積不超過(guò)背包容量,并且最終權(quán)值和最大,我們這時(shí)
就可以想到使用多重背包算法。
【實(shí)現(xiàn)】
我們可以先從背包容量最大的開(kāi)始直到背包容量為1,因?yàn)檫@樣子可以減少空間復(fù)雜度。為什么呢?f[j - vi[i] * k] + wi[i] * k
表示計(jì)算上一個(gè)的總價(jià)值再加上現(xiàn)在現(xiàn)在的價(jià)值 與 上一個(gè)包容量計(jì)算的價(jià)值進(jìn)行對(duì)比選擇最大值,這樣直接就大大減少了空間的浪費(fèi)
且數(shù)組只需要開(kāi)1維。
【具體】
根據(jù)方程
f[j] = max(f[j], f[j - vi[i] * k] + wi[i] * k);//比較上一個(gè)價(jià)值與當(dāng)前計(jì)算價(jià)值數(shù)
我們就可以選擇出目標(biāo)背包容量?jī)?nèi)的最大價(jià)值數(shù),然后進(jìn)行判斷最大數(shù)更新
【總結(jié)】
依然的,動(dòng)態(tài)規(guī)劃的特點(diǎn)就是解決了重復(fù)運(yùn)算的問(wèn)題,同時(shí)我們選擇倒序的方法也解決了開(kāi)二維數(shù)組而導(dǎo)致空間復(fù)雜度增加的問(wèn)題
#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; }
/*
以下是具體實(shí)現(xiàn)
*/
//v體積 w價(jià)值 c件數(shù),求最大權(quán)值和
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(物品數(shù))>=i>=1
for (unsigned int j = n; j >= 1; j--) {//j:當(dāng)前包容量 j - vi[i] * k=單個(gè)總?cè)萘? if (j - vi[i] >= 0) {
for (unsigned int k = 1; k <= ci[i]; k++) {//k=1-ci[i] 當(dāng)前件數(shù)
if (j >= vi[i] * k)//判斷體積是否超出限制
f[j] = ma(f[j], f[j - vi[i] * k] + wi[i] * k);//比較上一個(gè)價(jià)值與當(dāng)前計(jì)算價(jià)值數(shù)
if (f[j] > maxem)
maxem = f[j];//更新最大數(shù)
}
}
else
break;
}
}
cout << maxem;
return 0;
}