揹包九講 之 01揹包求方案數

2021-10-03 11:34:58 字數 1638 閱讀 6782

本文基於01揹包問題

問題重述

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出 最優選法的方案數。注意答案可能很大,請輸出答案模 109+7 的結果。

輸入格式:

第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。

接下來有 n 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。

輸出格式:

輸出乙個整數,表示 方案數 模 109+7 的結果。

資料範圍

0思路分析:

分析過01揹包後這道題便也容易解決,我們知道01揹包的狀態轉移方程是f[ i ][ j ] = max( f[ i -1][ j ] , f[ i-1 ][ j -v[i]]+wi )如果我們能記錄轉移到某種狀態的方案數,我們便可求最終的方案數。只需要加乙個陣列記錄每一種狀態的方案數,然後加乙個判斷,跟著狀態轉移就可。

即如果f[ i ][ j ]是由f[ i -1][ j ]f[ i -1][ j -v[i]]+wi其中一種狀態轉移過來的那麼它對應的狀態方案數就是,轉移過來的那個即counts[ i ][ j ] = counts[ i -1][ j ]或是counts[ i ][ j ] =counts[ i -1][ j -v[i]]如果兩者都能轉移到當前狀態那麼當前狀態的方案數就是兩者之和,即counts[ i ][ j ] = counts[ i -1][ j ] + counts[ i -1][ j -v[i]]。 那麼它對應的邊界情況也比較清晰即ij0counts[ i ][ j ]=1因為此時f[ i ][ j ]=0所以對應的方案數量就是1就只有它本身,因為它是邊界沒有辦法從它處轉移過來。

當然在01揹包問題中我們將狀態轉移方程最終優化到了f[ j ] = max( f[ j ] , f[ j -v[i]]+wi ),所以對應的我們用來記錄方案的陣列陣列也可以對應降到一維,即counts[ j ] = counts[ j ]或是counts[ j ] =counts[ j -v[i]]或是counts[ j ] = counts[ j ] + counts[ j -v[i]]

c++**:

#include

#include

using

namespace std;

intmain()

else

if(ans[j]

== ans[j-volume]

+value)

//最特殊的當二者相同時ans[j]也不需覆蓋}}

cout<

return0;

}

揹包九講 之 01揹包問題求具體方案

本文基於01揹包問題 問題重述 有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出 字典序最小的方案。這裡的字典序是指 所選物品的編號所構成的序列。物品的編號範圍是 ...

揹包九講之 01揹包

01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...

DP 揹包九講之01揹包

有n件物品和乙個容量為v 的揹包。放入第i件物品耗費的空間是ci,得到 的價值是wi。求解將哪些物品裝入揹包可使價值總和最大。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不 放。用子問題定義狀態 即f i,v 表示前i件物品恰放入乙個容量為v的揹包可以 獲得的最大價值。則其狀態轉移方...