揹包九講 01揹包問題(dp 滾動陣列)

2021-10-10 10:39:03 字數 2014 閱讀 9815

現在有n件物品和乙個容量為v的揹包。第i件物品的費用是cost[i],價值是value[i]。每個物品最多只能選一次,求解在不超過揹包容量的限制下,如何選取物品組合能使收益最大化?

題型有兩種,一種要求揹包恰好放滿,一種不要求揹包恰好放滿

現在考慮第二種題型,即不要求揹包恰好放滿

將問題分解成子問題:有i件物品,容量為j的揹包。

用dp[ i ][ j ]陣列儲存子問題的答案。

假設現在要求取dp[ i ] [ j ] ,我們考慮要不要選取第i件物品:

①如果不選取,則dp[ i ] [ j ]=dp[ i-1 ][ j ],因為dp陣列儲存的一直是當前狀態下最優的解,dp[ i-1 ][ j ]存放的值是在同樣容量為j的揹包限制下前i-1件物品最大的價值組合

②如果選取i件物品,考慮第i件物品的花費cost[ i ],則dp[ i ][ j ]=dp[ i-1] [ j-cost[i] ] +value [ i ] , 而 dp[ i-1] [ j-cost[i] ] 存放的值是容量為j-cost[ i ]限制下, 前i-1件物品最大的價值組合

綜上,得狀態轉移方程:

dp[ i ] [ j]=max(dp[ i-1 ][ j ], dp[ i-1] [j-cost[i] ] + value[ i ])

我們能保證不斷得到每乙個子問題的最優解,所以不斷遞推,即得到原問題的解

由之前的思路可得,解每乙個子問題dp[ i ][ j ]時,我們需要優先知道dp[ i-1 ][ j ]和dp[ i-1] [ j-cost[i] ] +value [ i ],觀察可得必須先知道dp陣列第i-1行的值

所有最外層迴圈讓i從小到大遞增

至於j是遞增還是遞減是無所謂的,因為求解子問題dp[ i ][ j ]時,我們只需要優先知道dp陣列第i-1行的值,至於第i行的求解順序是無所謂的

而考慮第一行,也就是只有一種物品時,那麼j是從小到大還是從大到小都無所謂,因為第一行的dp值只取決於j是否大於cost[1]

後面幾行都是第一行遞推而來,第一行沒問題後面幾行自然沒問題

int dp[10]

[2005];

memset

(dp,0,

sizeof

(dp));

for(

int i=

1;i<

8;i++

)for

(int j=n;j>=

1;j--

)

至於之前說的第一種題型,只要把dp陣列初始化為負無窮即可

負無窮表示沒有方案使該子問題得解

由之前的分析可以發現,求dp陣列第i行的值時,只需要用到dp陣列第i-1行的值,而其它幾行的值都是用不到的,所以為了節省空間,只需要用一維的dp陣列即可

但是要注意這其實是在用一維陣列來模擬二維陣列的情況,想象乙個不斷滾動的陣列

所以這裡的第二層迴圈中的j必須倒序了,不像之前是無所謂的了

原因很簡單,我們需要dp[ i-1] [ j-cost[ i ] ]的值,而如果j順序地從小到大增加則該值已經被覆蓋了,那麼該行後面的元素在計算時使用的就不是上一行的dp[ i-1] [ j-cost[ i ] ] ,其實已經被覆蓋為dp[ i] [ j-cost[ i ] ]

**:

int dp[

2005];

memset

(dp,0,

sizeof

(dp));

for(

int i=

1;i<

8;i++

)for

(int j=n;j>=

1;j--)if

(j>=cost[i]

) dp[j]

=max

(dp[j]

,dp[j-cost[i]

]+value[i]

);

同時也不需要else dp[i][j]=dp[i-1][j];這句**了 ,因為不變相當於不去覆蓋上一行的dp值

揹包九講 01揹包問題

1 01揹包問題描述 已知 有 n 件物品和乙個容量為 v 的揹包。第i件物品的重量為w i 得到的價值是 c i 問題 求解將哪些物品裝入揹包可使價值總和最大。條件 每種物品只有一件,可以選擇放或者不放 2 基本思路 01揹包的特點 每種物品只有一件,可以選擇放或者不放 子問題定義狀態f i v ...

DP 揹包九講之01揹包

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

DP 揹包九講之01揹包

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,每行兩個整數 ...