揹包問題是一類非常典型的動態規劃問題,包括多種型別(01揹包、完全揹包、多重揹包、混合揹包、二維費用揹包等)其基本型別為01揹包問題。
一、01揹包問題
n件物品,每件物品的重量和價值分別為 w[i], v[i], 把這些物品放到乙個容量為w的揹包中,求揹包中物品的價值的最大值。
分析
動態規劃要考慮最優子結構和無後效性,對於該問題,假設前i-1種物品在重量和約束w下得到了乙個最大價值和m,那麼在考慮前i種物品在重量和約束w'下價值的最大值m'時,我們只關心前i-1種物品的重量和w和最大價值和m,至於這前i-1種物品時如何選擇對求解m'無影響(因為m' = m + v[i],假設w + w[i] = w'),即無後效性;同時,前i種物品在重量約束w'下得到了價值的最大值,此時選取的物品集合為s,那麼s中必然包含前i-1種物品在重量約束w(w = w'或w = w'-w[i])下得到最大值的組合(用反證法可以證明),即最優子結構。因此考慮將問題規定為
前i種物品總重量不超過w時,能夠得到的最大價值 f[i][w]
。此時有遞推公式
f[i][w] = max(f[i-1][w], f[i-1][w - w[i]] + v[i])//情形1.不選擇第i種物品,那麼前i種物品可得到的最大值為 f[i-1][w];
//情形2.選擇第i種物品,那麼前i-1種物品可以使用 w -w[i]的空間存放,前i-1種物品可得最大價值 f[i-1][w-w[i]], 再加上第i種物品的價值 v[i]
//在二者中間取最大值即可。
針對實際問題設定邊界條件
優化
實現
for(int i = 0; i <= w; i ++)for(int i = 1; i <= n; i ++)
}
複雜度分析
二、完全揹包問題
有n種物品,每種物品有個重量w[i]和價值v[i],每種物品可以選擇無限多件。給定乙個承重不超過 w的揹包,求出揹包中所放物品的價值和的最大值。和01揹包問題一樣分析,設 f[i][w]表示前i種物品中選擇總重不超過w的物品所能得到的價值和的最大值。有
f[i][w] = max | k屬於[1, w/w[i]]
分析
觀察f[i][w] = max | k屬於[0, w/w[i]],max= max | k屬於[1, w/w[i]],
令k = t+1, 則
max | k屬於[1, w/w[i]],
= max + v[i] | t屬於[0, (w-w[i])/w[i]],
= f[i-1][w - w[i]] + v[i]
因此f[i][w] = max
實現
for(int i = 0; i <= w; i ++)for(int i = 0; i <= n; i ++);
}}
複雜度分析
對比01揹包和完全揹包
三、多重揹包問題
n種物品,第i種物品的重量值為w[i], 價值為v[i],且第i種物品有c[i]個。給定揹包的承重w,求能放入揹包中的物品總價值的最大值。分析
給定乙個正整數n,可以用1, 2,... 2^(k-1), n - 2^k + 1這些數(約log(n)個)來表示[1,n]中的任何乙個整數,其中k為使得n - 2^k + 1 > 0的最大的正整數
此時時間複雜度為o(w*(∑n1log2(c[i])
int weight[max];int value[max];
void expand(int w, int v, int n, int& index)while(k*2 < n);
weight[index] = (n - k + 1)*w;
value[index++] = (n - k + 1)*v;
}
四、混合揹包問題
for(int i = 1; i <= n; i ++);}}else if(物品i為完全揹包物品);}}
}
五、二維費用的揹包問題
n中物品,每件物品i都有兩種不同的空間消耗,選擇這件物品必須同時付出這兩種代價。對於每種代價都有乙個可付出的最大值(揹包容量),問怎樣選擇物品使得總價值和最大。分析
六、分組的揹包問題
有n件物品和乙個容量為v的揹包。第i件物品的費用是ci,價值是wi。這些物品被劃分為k組,每組中的物品互相衝突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。分析
for k = 1 to k //組for w = w to 0 //承重
for item i in group k //組內的每個物品
f[w] = max
七、揹包問題的相關問題
7.1 輸出選取物品方案
如果不僅僅需要求出揹包所承載物品的最大價值,還需要求出揹包中選取的物品集合。則還需要維護另乙個陣列g[i][w], 若 f[i][w] == f[i-1][w]表示第i件物品沒有被選擇,則令g[i][w] = 0;若 f[i][w] == f[i-1[w - w[i]] + v[i],則說明選擇了第i件物品,則令g[i][w] = 1,這樣在求解f陣列的時候順便求出g陣列。
int i = n, w = w;while(i >= 1)else
i --;
}
7.2 輸出字典序最小的最優方案
7.3 最優方案總數
g[0][0] = 1for(int i = 1; i <= n; i ++);
g[i][w] = 0;
if(f[i][w] == f[i-1][w])
if(f[i][w] == f[i-1][w-w[i]] + v[i])
}}
7.4 求第k優解
對於求次優解、第k優解類的問題,如果相應的最優解問題能寫出狀態轉移方程、用動態規劃解決,那麼求次優解往往可以相同的複雜度解決,第k優解則比求最優解的複雜度上多乙個係數k。
for(int i = 1; i <= n; i ++)elset ++; }}
}//時間複雜度為o(nwk);
參考
《揹包九講》
動態規劃 揹包問題
給定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 元。於是,他把每...