本文為網上覆制
本人博文《揹包問題——「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
?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
?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...