在
0 / 1
揹包問題中,需對容量為
c 的揹包進行裝載。從
n 個物品中選取裝入揹包的物品,每件物品
i 的重量為
wi ,價值為
pi .
對於可行的揹包裝載,揹包中物品的總重量不能超過揹包的容量,最佳裝載是指所裝入的物品價值最高,即n ?
i=1pi xi
取得最大值。約束條件為n ?
i =1wi xi≤c 和xi
?[ 0
,1 ]
(1≤i≤n)。
在這個表示式中,需求出
xt 的值。
xi = 1
表示物品
i 裝入揹包中,
xi =0
表示物品
i 不裝入揹包。
0 / 1
揹包問題是乙個一般化的貨箱裝載問題,即每個貨箱所獲得的價值不同。貨箱裝載問題轉化為揹包問題的形式為:船作為揹包,貨箱作為可裝入揹包的物品。
例1-8
在雜貨店比賽中你獲得了第一名,獎品是一車免費雜貨。店中有
n 種不同的貨物。規則規定從每種貨物中最多只能拿一件,車子的容量為
c,物品
i 需占用
wi 的空間,價值為
pi .
你的目標是使車中裝載的物品價值最大。當然,所裝貨物不能超過車的容量,且同一種物品不得拿走多件。這個問題可仿照
0 / 1揹包問題進行建模,其中車對應於揹包,貨物對應於物品。
0 / 1
揹包問題有好幾種貪婪策略,每個貪婪策略都採用多步過程來完成揹包的裝入。在每一步過程中利用貪婪準則選擇乙個物品裝入揹包。一種貪婪準則為:從剩餘的物品中,選出可以裝入揹包的價值最大的物品,利用這種規則,價值最大的物品首先被裝入(假設有足夠容量),然後是下乙個價值最大的物品,如此繼續下去。這種策略不能保證得到最優解。例如,考慮
n=2,
w=[100,10
,10]
,p =[20,15
,15]
,c = 1 0 5.
當利用價值貪婪準則時,獲得的解為
x= [ 1 ,0
,0 ]
,這種方案的總價值為
2 0.
而最優解為
[ 0 ,1
,1 ]
,其總價值為
3 0.
另一種方案是重量貪婪準則是:從剩下的物品中選擇可裝入揹包的重量最小的物品。雖然這種規則對於前面的例子能產生最優解,但在一般情況下則不一定能得到最優解。考慮
n= 2
,w=[10
,20]
,p=[5
,100]
,c= 2 5.
當利用重量貪婪策略時,獲得的解為
x =[1,0]
,比最優解
[ 0
,1 ]要差。
還可以利用另一方案,價值密度
pi /wi
貪婪演算法,這種選擇準則為:從剩餘物品中選擇可裝入包的
pi /wi
值最大的物品,這種策略也不能保證得到最優解。利用此策略試解
n= 3
,w=[20,15
,15]
,p=[40,25
,25]
,c=30時的最優解。
我們不必因所考察的幾個貪婪演算法都不能保證得到最優解而沮喪,
0 / 1
揹包問題是乙個
n p-
複雜問題。對於這類問題,也許根本就不可能找到具有多項式時間的演算法。雖然按
pi /wi
非遞(增)減的次序裝入物品不能保證得到最優解,但它是乙個直覺上近似的解。我們希望它是乙個好的啟發式演算法,且大多數時候能很好地接近最後演算法。在
6 0 0
個隨機產生的揹包問題中,用這種啟發式貪婪演算法來解有
2 3 9
題為最優解。有
5 8 3
個例子與最優解相差
1 0 %
,所有6 0 0
個答案與最優解之差全在
2 5 %
以內。該演算法能在o (
nl o gn
)時間內獲得如此好的效能。我們也許會問,是否存在乙個x (
x<1 0 0
),使得貪婪啟發法的結果與最優值相差在
x%以內。答案是否定的。為說明這一點,考慮例子
n =2
,w = [ 1 ,y]
,p= [ 1 0
,9y],和
c= y.
貪婪演算法結果為
x=[1,0]
,這種方案的值為
1 0.
對於y≥1 0 / 9
,最優解的值為
9 y.
因此,貪婪演算法的值與最優解的差對最優解的比例為(
(9y - 1 0
)/9y* 1 0 0 )%
,對於大的
y,這個值趨近於
1 0 0 %.
但是可以建立貪婪啟發式方法來提供解,使解的結果與最優解的值之差在最優值的
x% (
x<100
)之內。首先將最多
k 件物品放入揹包,如果這
k 件物品重量大於
c,則放棄它。否則,剩餘的容量用來考慮將剩餘物品按
pi /wi
遞減的順序裝入。通過考慮由啟發法產生的解法中最多為
k件物品的所有可能的子集來得到最優解。
例13-9
考慮n =4
,w=[2,4
,6,7]
,p=[6,10
,12,13]
,c = 11.
當k= 0
時,揹包按物品價值密度非遞減順序裝入,首先將物品
1放入揹包,然後是物品
2,揹包剩下的容量為
5個單元,剩下的物品沒有乙個合適的,因此解為
x = [ 1 ,1
,0 ,0 ].
此解獲得的價值為
1 6.
現在考慮
k = 1
時的貪婪啟發法。最初的子集為 ,
, ,.子集 ,
產生與k= 0
時相同的結果,考慮子集
,置x3 為1.
此時還剩
5個單位的容量,按價值密度非遞增順序來考慮如何利用這
5個單位的容量。首先考慮物品
1,它適合,因此取
x1 為
1,這時僅剩下
3個單位容量了,且剩餘物品沒有能夠加入揹包中的物品。通過子集
開始求解得結果為
x = [ 1 ,0
,1 ,0 ]
,獲得的價值為
1 8.
若從子集
開始,產生的解為
x = [ 1 ,0
,0 ,1 ]
,獲得的價值為
1 9.
考慮子集大小為0和
1時獲得的最優解為
[ 1 ,0
,0 ,1 ].
這個解是通過
k= 1的貪婪啟發式演算法得到的。
若k= 2
,除了考慮
k< 2
的子集,還必需考慮子集 ,
, ,,和.
首先從最後乙個子集開始,它是不可行的,故將其拋棄,剩下的子集經求解分別得到如下結果:
[ 1 ,1
,0 ,0 ]
,[ 1 ,0
,1 ,0 ]
,[ 1 ,0
,0 ,1 ]
,[ 0 ,1
,1 ,0 ]
和[ 0 ,1
,0 ,1 ]
,這些結果中最後乙個價值為
2 3,它的值比
k= 0
和k= 1
時獲得的解要高,這個答案即為啟發式方法產生的結果。
這種修改後的貪婪啟發方法稱為
k階優化方法(
k - o p t i m a l
)。也就是,若從答案中取出
k 件物品,並放入另外
k 件,獲得的結果不會比原來的好,而且用這種方式獲得的值在最優值的(
1 0 0 /
(k + 1 ))
%以內。當
k= 1
時,保證最終結果在最佳值的
5 0 %
以內;當
k= 2
時,則在
3 3 . 3 3 %
以內等等,這種啟發式方法的執行時間隨
k的增大而增加,需要
測試的子集數目為
o
(nk
),每乙個子集所需時間為o (
n),因此當
k >0
時總的時間開銷為o (
nk+1)。實際觀察到的效能要好得多。
演算法之揹包
不死族的巫妖王發工資拉,死亡騎士拿到一張n元的鈔票 記住,只有一張鈔票 為了防止自己在戰鬥中頻繁的死掉,他決定給自己買一些道具,於是他來到了地精商店前.死亡騎士 我要買道具 地精商人 我們這裡有三種道具,血瓶150塊乙個,魔法藥200塊乙個,無敵藥水350塊乙個.死亡騎士 好的,給我乙個血瓶.說完他...
經典演算法詳解 之 揹包演算法
揹包問題 knapsackproblem 是一種組合優化的 np完全問題 問題可以描述為 給定一組物品,每種物品都有自己的重量和 在限定的總重量內,我們如何選擇,才能使得物品的總 最高。這個問題涉及到了兩個條件 一是物品總的大小小於或等於揹包的大小,二是物品總的價值要盡量大。如果我們 用子問題定義狀...
經典演算法詳解 之 揹包演算法
揹包問題 knapsackproblem 是一種組合優化的 np完全問題 問題可以描述為 給定一組物品,每種物品都有自己的重量和 在限定的總重量內,我們如何選擇,才能使得物品的總 最高。這個問題涉及到了兩個條件 一是物品總的大小小於或等於揹包的大小,二是物品總的價值要盡量大。如果我們 用子問題定義狀...