「01揹包」最優方案總數分析及實現

2021-06-07 22:09:09 字數 2695 閱讀 2575

本文為網上覆制

本人博文《揹包問題——「01揹包」詳解及實現(包含揹包中具體物品的求解)>>中已談過01揹包,這裡再重寫一下01揹包的動態規劃狀態及狀態方程:

設揹包容量為v,一共n件物品,每件物品體積為c[i],每件物品的價值為w[i]

1) 子問題定義:f[i][j]表示前i件物品中選取若干件物品放入剩餘空間為j的揹包中所能得到的最大價值。

2) 根據第i件物品放或不放進行決策

(1-1)

最優方案總數這裡指物品總價值最大的方案數。

我們設g[i][j]代表f[i][j]的方案總數,那麼最總結果應該是g[n][v]。我們初始化g為1,因為對每個f[i][j]至少應該有一種方案,即前i件物品中選取若干件物品放入剩餘空間為j的揹包使其價值最大的方案數至少為1,因為f[i][j]一定存在。

下面開始分析怎麼求g[i][j]。對於01揹包來說:

如果f[i][j]=f[i-1][j]且f[i][j]!=f[i-1][j-c[i]]+w[i]說明在狀態[i][j]時只有前i-1件物品的放入才會使價值最大,所以第i件物品不放入,那麼到狀態[i][j]的方案數應該等於[i-1][j]狀態的方案數即g[i][j]=g[i-1][j]

如果f[i][j]=f[i-1][j-c[i]]+w[i] 且f[i][j]!=f[i-1][j]說明在狀態[i][j]時只有第i件物品的加入才會使總價值最大,那麼方案數應該等於[i-1][j-c[i]]的方案數,即g[i][j]=g[i-1][j-c[i]]

如果f[i][j]=f[i-1][j-c[i]]+w[i] 且f[i][j]=f[i-1][j]則說明即可以通過狀態[i-1][j]在不加入第i件物品情況下到達狀態[i][j],又可以通過狀態[i-1][j-c[i]]在加入第i件物品的情況下到達狀態[i][j],並且這兩種情況都使得價值最大且這兩種情況是互斥的,所以方案總數為g[i][j]=g[i-1][j-c[i]]+ g[i-1][j]

經過上面的分析,得出下述偽**:

[cpp]view plain

copy

print

?f[0] ← 0  

f[0] ← 0  

g[ ] ← 1  

for i ← 1 to n  

do for j ← 1 to v  

f[i][j] ← f[i-1][j]  

g[i][j] ← g[i-1][j]  

if (j >= c[i])  

if (f[i][j] < f[i-1][j-c[i]]+w[i])  

then f[i][j] ← f[i-1][j-c[i]]+w[i]  

g[i][j] ← g[i-1][j-c[i]]  

else if (f[i][j] = f[i-1][j-c[i]]+w[i])  

then g[i][j] ← g[i-1][j]+g[i-1][j-c[i]]  

return f[n][v] and g[n][v]  

f[0] ← 0 f[0] ← 0 g[ ] ← 1 for i ← 1 to n do for j ← 1 to v f[i][j] ← f[i-1][j] g[i][j] ← g[i-1][j] if (j >= c[i]) if (f[i][j] < f[i-1][j-c[i]]+w[i]) then f[i][j] ← f[i-1][j-c[i]]+w[i] g[i][j] ← g[i-1][j-c[i]] else if (f[i][j] = f[i-1][j-c[i]]+w[i]) then g[i][j] ← g[i-1][j]+g[i-1][j-c[i]] return f[n][v] and g[n][v]

上述方法在儲存狀態f及g時需要o(nv)的空間複雜度,下面我們對空間復制度進行優化。

壓縮空間複雜度為o(v)

f[i][j]與g[i][j]只分別與f[i-1]和g[i-1]的狀態有關,所以我們可以用兩個一維陣列f和g來替換二維陣列f和g。具體思想請看博文

《揹包問題——「01揹包」詳解及實現(包含揹包中具體物品的求解)>>

下面直接給出偽**:

[cpp]view plain

copy

print

?f ← 0  

g ← 1  

for i ← 1 to n  

do for j ← v to c[i]  

if (f[j] < f[j-c[i]]+w[i])  

then f[j] ← f[j-c[i]]+w[i]  

g[j] ← g[j-c[i]]  

else if (f[j] = f[j-c[i]]+w[i])  

then g[j] ← g[j]+g[j-c[i]]  

return f[v] and g[v]  

f ← 0 g ← 1 for i ← 1 to n do for j ← v to c[i] if (f[j] < f[j-c[i]]+w[i]) then f[j] ← f[j-c[i]]+w[i] g[j] ← g[j-c[i]] else if (f[j] = f[j-c[i]]+w[i]) then g[j] ← g[j]+g[j-c[i]] return f[v] and g[v]

揹包問題 「01揹包」最優方案總數分析及實現

edit by zhusenlin hdu 本人博文 揹包問題 01揹包 詳解及實現 包含揹包中具體物品的求解 中已談過01揹包,這裡再重寫一下01揹包的動態規劃狀態及狀態方程 設揹包容量為v,一共n件物品,每件物品體積為c i 每件物品的價值為w i 1 子問題定義 f i j 表示前i件物品中選...

揹包問題之最優方案總數

此處的最優方案是指物品總價值最大的方案。這裡以0 1揹包問題為例。給定資料如下 c 2 3,4 5,6 7,8 v 3,4,5,6,7,8,9 v 23 結合求最大總價值和方案總數兩個問題的思路,最優方案的總數可採取如下方式求解 令 dp i j dp i j dp i j 表示前i件物品在代價為j...

完全揹包求方案總數

給定乙個正整數n,求將其分解成若干個素數之和的方案總數。這題和p1164 小a點菜很像,但是那題是01揹包,這題是完全揹包。include include include include include define int long long using namespace std const i...