C語言算法之揹包算法

0 / 1揹包問題中,需對容量爲的揹包進行裝載。從個物品中選取裝入揹包的物品,每件物品的重量爲wi ,價值爲pi .對於可行的揹包裝載,揹包中物品的總重量不能超過揹包的容量,最佳裝載是指所裝入的物品價值最高,即i=1pi xi 取得最大值。約束條件爲i =1wi xi≤c xi[ 0  1 ]  1≤i≤n)。

    在這個表達式中,需求出xt 的值。xi = 1表示物品裝入揹包中,xi =0 表示物品不裝入揹包。0 / 1揹包問題是一個一般化的貨箱裝載問題,即每個貨箱所獲得的價值不同。貨箱裝載問題轉化爲揹包問題的形式爲:船作爲揹包,貨箱作爲可裝入揹包的物品。 1-8 在雜貨店比賽中你獲得了第一名,獎品是一車免費雜貨。店中有種不同的貨物。規則規定從每種貨物中最多隻能拿一件,車子的容量爲c,物品需佔用wi 的空間,價值爲pi .你的目標是使車中裝載的物品價值最大。當然,所裝貨物不能超過車的容量,且同一種物品不得拿走多件。這個問題可仿照0 / 1揹包問題進行建模,其中車對應於揹包,貨物對應於物品。

    0 / 1揹包問題有好幾種貪婪策略,每個貪婪策略都採用多步過程來完成揹包的裝入。在每一步過程中利用貪婪準則選擇一個物品裝入揹包。一種貪婪準則爲:從剩餘的物品中,選出可以裝入揹包的價值最大的物品,利用這種規則,價值最大的物品首先被裝入(假設有足夠容量),然後是下一個價值最大的物品,如此繼續下去。這種策略不能保證得到最優解。例如,考慮n=2 w=[1001010] p =[201515] c = 1 0 5.當利用價值貪婪準則時,獲得的解爲x= [ 1  0  0 ],這種方案的總價值爲2 0.而最優解爲[ 0  1 ],其總價值爲3 0.

    另一種方案是重量貪婪準則是:從剩下的物品中選擇可裝入揹包的重量最小的物品。雖然這種規則對於前面的例子能產生最優解,但在一般情況下則不一定能得到最優解。考慮n= 2 w=[1020] p=[5100] c= 2 5.當利用重量貪婪策略時,獲得的解爲x =[10] 比最優解[ 0  1 ]要差。

    還可以利用另一方案,價值密度pi /wi 貪婪算法,這種選擇準則爲:從剩餘物品中選擇可裝入包的pi /wi 值最大的物品,這種策略也不能保證得到最優解。利用此策略試解n= 3 w=[201515] p=[402525] c=30 時的最優解。

    我們不必因所考察的幾個貪婪算法都不能保證得到最優解而沮喪, 0 / 1揹包問題是一個N P-複雜問題。對於這類問題,也許根本就不可能找到具有多項式時間的算法。雖然按pi /wi 非遞(增)減的次序裝入物品不能保證得到最優解,但它是一個直覺上近似的解。我們希望它是一個好的啓發式算法,且大多數時候能很好地接近最後算法。在6 0 0個隨機產生的揹包問題中,用這種啓發式貪婪算法來解有2 3 9題爲最優解。有5 8 3個例子與最優解相差1 0 %,所有6 0 0個答案與最優解之差全在2 5 %以內。該算法能在nl o gn)時間內獲得如此好的性能。我們也許會問,是否存在一個x<1 0 0 ),使得貪婪啓發法的結果與最優值相差在x%以內。答案是否定的。爲說明這一點,考慮例子n =2 w = [ 1 y] p= [ 1 0  9y] c= y.貪婪算法結果爲x=[10] 這種方案的值爲1 0.對於y≥1 0 / 9,最優解的值爲9 y.因此,貪婪算法的值與最優解的差對最優解的比例爲(  9y - 1 0/9y* 1 0 0  %,對於大的y,這個值趨近於1 0 0 %.但是可以建立貪婪啓發式方法來提供解,使解的結果與最優解的值之差在最優值的x% x<100 之內。首先將最多件物品放入揹包,如果這件物品重量大於c,則放棄它。否則,剩餘的容量用來考慮將剩餘物品按pi /wi 遞減的順序裝入。通過考慮由啓發法產生的解法中最多爲件物品的所有可能的子集來得到最優解。

    13-9 考慮n =4 w=[2467] p=[6101213] c = 11.k= 0時,揹包按物品價值密度非遞減順序裝入,首先將物品1放入揹包,然後是物品2,揹包剩下的容量爲5個單元,剩下的物品沒有一個合適的,因此解爲x = [ 1  1  0  0 ].此解獲得的價值爲1 6.

    現在考慮k = 1時的貪婪啓發法。最初的子集爲{ 1 }  { 2 }  { 3 }  { 4 }.子集{ 1 }  { 2 }產生與k= 0時相同的結果,考慮子集{ 3 },置x3 1.此時還剩5個單位的容量,按價值密度非遞增順序來考慮如何利用這5個單位的容量。首先考慮物品1,它適合,因此取x1 1,這時僅剩下3個單位容量了,且剩餘物品沒有能夠加入揹包中的物品。通過子集{ 3 }開始求解得結果爲x = [ 1  0  1  0 ],獲得的價值爲1 8.若從子集{ 4 }開始,產生的解爲x = [ 1  0  0  1 ],獲得的價值爲1 9.考慮子集大小爲01時獲得的最優解爲[ 1  0  0  1 ].這個解是通過k= 1的貪婪啓發式算法得到的。

    k= 2,除了考慮k< 2的子集,還必需考慮子集{ 1  2 }  { 1  3 }  { 1  4 }  { 2  3 }  { 2  4 }{ 3  4 }.首先從最後一個子集開始,它是不可行的,故將其拋棄,剩下的子集經求解分別得到如下結果:[ 1  1  0  0 ]  [ 1  0  1  0 ]  [ 1  0  0  1 ]  [ 0  1  1  0 ][ 0  1  0  1 ],這些結果中最後一個價值爲2 3,它的值比k= 0k= 1時獲得的解要高,這個答案即爲啓發式方法產生的結果。 這種修改後的貪婪啓發方法稱爲k階優化方法(k - o p t i m a l)。也就是,若從答案中取出件物品,並放入另外件,獲得的結果不會比原來的好,而且用這種方式獲得的值在最優值的( 1 0 0 / k + 1   %以內。當k= 1時,保證最終結果在最佳值的5 0 %以內;當k= 2時,則在3 3 . 3 3 %以內等等,這種啓發式方法的執行時間隨的增大而增加,需要測試的子集數目爲nk ),每一個子集所需時間爲n),因此當k >0時總的時間開銷爲nk+1 )。實際觀察到的性能要好得多。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章