有n個物品,且每個物品都只有乙個。物品i的體積為v[ i ],重量為w[ i ]。揹包的體積為c,求怎樣裝載能使得揹包裡裝的物品最重?
之所以叫0-1揹包問題,是因為所有的物品都只有乙個,在選擇物品裝載到揹包裡的時候,只有兩種選擇:不裝載或裝載,對應計算機裡的0(false)和1(true)的概念。我們用 dp[ i ][ j ] 表示「把前 i 個物品裝到體積為 j 的揹包中的最大總重量」。得狀態轉移方程:
dp[i][j] = max(dp[i-1][j], dp[i-1][j - v[i]] + w[i]);
其中,dp[ i - 1 ][ j ] 表示不把物品 i 裝載進揹包,所以揹包的重量是前面 i-1 個的重量;後一項 dp[ i - 1][ j - v[ i ] ] + w[ i ] 表示若把第 i 個物品裝載進揹包,則必須由最優子問題得到,所以沒裝載 i 之前重量一定也是最大的。
我們發現迴圈的時候,這個轉移方程是乙個二維陣列,且第 i 行取決於第 i -1行的值,因此初始化時,只要將第 0 行全部置為 0 即可,即 dp[ 0 ] [ j ] = 0;
for(int j = 0; j <= c; ++ j)
for(int i = 1; i <= n; ++ i) else
}}
dp[ i ][ j ] 表示「把前 i 個物品裝到體積為 j 的揹包中的最大總重量」。所以外迴圈 i 表示從前1個物品到前n個物品,內迴圈 j 表示體積從 0 到 最大的 c。由於資料是一樣樣計算的,所以可以不用提前把所有的資料都讀好,也不用存起來。
更奇妙的是,我們可以把陣列dp程式設計一維的,這裡非常的精妙和巧合,但是要注意這只是程式**的優化,並不是說 0 - 1 揹包問題就是一維揹包問題。
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; ++ i)
}
考慮為採用滾動陣列的情況,f[ i ][ j ]的值要麼是f[ i - 1][ j ],要麼是f[ i - 1][ j - v ] + w;由於j是從右往左計算的,所以現在f[j]裡儲存的是f[ i - 1 ] [ j ],而f[j - v]裡儲存的是f[ i - 1 ] [ j - v ]的值,所以正好可以。這樣子的話,我們可以節省了不少空間的代價。
注意內迴圈 j 是到 v 即停止了的,這樣子就不用判斷 j 和 v 的關係了,因為 j >= v 始終成立。若是 j < v 的情況,f[ j ] 中本來就儲存了 f[ i - 1][ j ]的資訊,也不用更新。
此外,若題目要求,揹包必須裝滿,則只需要改一下初始化的條件就行。
memset(dp, -0x3f3f, sizeof(dp));
dp[0] = 0;
for(int i = 1; i <= n; ++ i)
}
揹包九講裡是這樣子解釋的:初始化的過程,實際就是說,當一件物品都沒有時的解。所以若要求必須裝滿揹包,只有一種解,就是dp[0],即讓價值為0的物品,恰好裝進容量為0的包裡。其他的都是非法解,所以初始化為負∞才行。而沒有要求一定要裝滿揹包的情況下,則所有的解都可以是正確的解,所以可以初始化為0;
可重複揹包是說,每種物品的個數是無限的,而不是0-1揹包中,物品只有乙個。相似的,有狀態轉移方程:
dp[i][v]=max
就是說,這個物品可以選 0 次,1 次,2次... v / c[i] 次,知道裝不下為止。
但是也有o(nv)複雜度的優化,而且**很簡單,就是上面的滾動陣列實現0-1揹包,內迴圈 j 倒過來就行了。原理不明,可能是我水平太低了,目前無法理解。
偽**如下:
procedure completepack(cost,weight)
for v=cost..v
f[v]=max
動態規劃 揹包問題
給定n個物品,重量是,價值是,包的容量 承重 是w 問,放入哪些物品能使得包內價值最大 1 需要將問題轉化為子問題,通過遞迴實現,且子問題必然與父問題存在關聯 2 定義v i,j 表示為,當item取自前i個items且揹包capacity j 時,揹包問題的最優解,也即最高的價值。3 從前i個it...
動態規劃 揹包問題
不廢話,直接上 動態規劃,揹包問題。輸入為 int n 物品的種類數。int n weight 各件物品的重量。int n value 各種物品的價值。int w 揹包最大的裝載重量。輸出 v n b 的值,最大的裝載價值。x n 各類物品的裝載數量。author huangyongye publi...
動態規劃 揹包問題
1 開心的金明 問題描述 金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n 元錢就行 今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的n 元。於是,他把每...