(推薦 : )
學會了前兩個揹包 , 學這個揹包還是很輕鬆的 。
多重揹包 , 顧名思義 , 就是前兩種揹包結合到一起 , 首先還是用乙個例子說明 。
1、問題描述
已知:有乙個容量為v的揹包和n件物品,第i件物品最多有num[i]件,每件物品的重量是weight[i],收益是cost[i]。
問題:在不超過揹包容量的情況下,最多能獲得多少價值或收益
多重揹包 區別於二重揹包的地方就在於 所給出的物品數是有限的 。
用二維陣列寫出** :
#include #include #include #include using namespace std ;上述的優化方法就採用了二進位制的思想#define max(a,b) a>b?a:b
#define min(a,b) a>b?b:a
int dp[100][1000] ;
int weight[10] ;
int value[10] ;
int num[10] ;
int main ( )
for ( int i = 1 ; i <= n ; i++ )
}// cout << '\n' ;
}cout << dp[n][v] << endl ;
return 0 ;
}
對每件物品拆分 , 拆分的數量可以是 1件 、 2件 、 4件 ……2^k 件,並且要保證 2^k <= num[ i ] ,但是這裡的最後一件是 num[ i ] - 前面所有物品的和 , 那麼對 num[ i ] 來說 , 就一定會有前面的 數相加等於 num[ i ] ,其實這樣對物品拆分 , 在取得話 , 就可以看成每件新拆分出的物品只有一件 , 進而不就轉換成 01揹包了嗎 ,一定要注意領悟這個拆分的思想 , 是講揹包的物品總數分解開 。
優化 :
說到拆分 , 有種情況是不用拆分的 , 就是當 weight[ i ] * num[ i ] >= v ,因為這種情況就可以理解成物品的數量充足 ,那麼不就轉化成 完全揹包的情況嗎 ? 直接就會被優化到 o(v*n) 。
對於不滿足完全揹包情況的物品進行拆分 , 此時物品的個數就沒有對所有物品進行拆分的個數多 , 那麼迴圈的次數就會降下來 , 複雜度也就降低了 。
**示例 :
#include using namespace std;const int n = 3;//物品個數
const int v = 8;//揹包容量
int weight[n + 1] = ;
int value[n + 1] = ;
int num[n + 1] = ;
int f[v + 1] = ;
/* f[v]:表示把前i件物品放入容量為v的揹包中獲得的最大收益。
f[v] = max(f[v],f[v - weight[i]] + value[i]);
v的為逆序
*/
void zeroonepack(int nweight,int nvalue)
} /*
f[v]:表示把前i件物品放入容量為v的揹包中獲得的最大收益。
f[v] = max(f[v],f[v - weight[i]] + value[i]);
v的為增序
*/
void completepack(int nweight,int nvalue)
} int multiknapsack()
else
zeroonepack(ncount * weight[i],ncount * value[i]);
} }
return f[v];
}
int main()
{ cout<
dp 揹包之多重揹包
問題 多重揹包也是 0 1 揹包的乙個變式。與 0 1 揹包的區別在於每種物品有ki個,而非乙個。解決方案 將k個相同的物品,看作k個不同的物品,但是wi,ci都一樣。即可套用 01揹包方案 詳見 優化方法 二進位制優化 設k個物品分成 a xx a xx 1 a xx k 1 個物品。那麼 a x...
DP之多重揹包
description 給定n種物品和乙個容量為c的揹包,第i種物品最多有mi件可用,每件的重量是wi,價值是vi。問 將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。input 輸入的第一行為測試樣例的個數t,接下來有t個測試樣例。每個測試樣例的第一行是物品種數n 1 n ...
揹包DP(01揹包,多重揹包,完全揹包)
從前乙個轉態轉移過來,選還是不選 for int i 1 i n i else f i j f i 1 j 01揹包優化 滾動陣列 for int i 1 i n i for int j m j 1 j if weight i j f j max f j f j weight i value i 優...