孫佳寧,馬海龍,張立臣,李 鵬*
(1.現(xiàn)代教學(xué)技術(shù)教育部重點實驗室,陜西 西安 710062;2.陜西省教學(xué)信息技術(shù)工程實驗室,陜西 西安 710119;3.陜西師范大學(xué) 計算機科學(xué)學(xué)院,陜西 西安 710119)
背包問題是指,在指定的背包容量下,如何選擇總價值最大的物品裝入背包。在背包問題中,若每個物品只能被選擇一次,且裝入時不可拆分,稱為0-1背包問題。0-1背包問題是組合優(yōu)化問題中經(jīng)典的NP完全問題,一直以來得到廣泛的研究和應(yīng)用,如貨物裝載、投資選擇、密鑰生成等。
隨著科技的發(fā)展和新型算法策略的不斷涌現(xiàn),0-1背包問題的求解算法也由經(jīng)典的蠻力法、貪心算法、動態(tài)規(guī)劃法、回溯法、分支限界法等逐漸發(fā)展出眾多新型智能算法,如螢火蟲算法、量子狼群算法、煙花算法、混合蝙蝠算法等。這些新型算法在一定程度上能夠提高搜索能力和求解速度,但并不能保證找到問題的最優(yōu)解,其算法的高效性是以犧牲算法的最優(yōu)性為代價的。
在保證得到0-1背包問題最優(yōu)解的前提下,該文以貪心算法和回溯算法為基準(zhǔn),以提高算法性能為目標(biāo),對其進(jìn)行改進(jìn),提出了一種新型回溯算法。該算法利用了“回溯算法在搜索過程中判斷、調(diào)試”的特點,并通過先運行得到的貪心算法的近似解用于經(jīng)典回溯算法剪枝策略的判斷條件,同時優(yōu)化了該算法中針對物品選擇的判斷條件。
通過大量的仿真實驗,如設(shè)置每個物品的重量和價值、背包的容量、背包可容納的物品數(shù)量的最大上限等,設(shè)計對比實驗,觀察和分析了經(jīng)典的回溯算法與該文提出的新型回溯算法找到問題最優(yōu)解時的時間耗費,驗證所提出算法的高效性和可靠性。
經(jīng)典的0-1背包問題指的是給定一些物品和一個背包,每個物品的重量和價值已知,背包的容量已知。選擇一定的物品裝入背包,在選擇的過程中,要求每個物品只能被選擇一次,且每次只有裝入或不裝入兩種選項(即物品不可分割)。如何進(jìn)行物品的選擇,才能使放入背包的物品總重量在不超過背包容量的前提下,擁有最大的價值總和。
假設(shè)物品數(shù)量為n
,背包容量為C
,第i
個物品的重量為w
[i
],價值為v
[i
],則0-1背包問題的形式化模型表示如下:x
[i
]表示物品i
的選擇狀態(tài),x
[i
]=1表示選中第i
個物品放入背包,x
[i
]=0表示第i
個物品沒有放入背包。眾所周知,貪心算法兼顧了問題求解的可行性和算法執(zhí)行的高效性,是近似解決最優(yōu)化問題較簡單、較迅速的求解算法。在問題求解的過程中,貪心算法并不考慮問題的整體性,只考慮當(dāng)前條件下的最優(yōu)選擇,通過局部最優(yōu)解逐步構(gòu)造出問題的解,因而往往只能得到問題的近似最優(yōu)解。
常見的貪心策略有“物品重量最小優(yōu)先”、“物品價值最大優(yōu)先”和“物品單位價值最大優(yōu)先”。在實際應(yīng)用中,“物品單位價值最大優(yōu)先”的貪心策略往往效果最好,因而該文采用該貪心策略,其主要步驟描述如下:
(1)計算每個物品的單位重量價值,并按照該單位價值以遞減順序?qū)ξ锲愤M(jìn)行排序,排序后的結(jié)果存儲到一維數(shù)組index中;
(2)根據(jù)排序后的結(jié)果,按照單位價值從大到小的順序,依次將每個物品放入背包,直到背包內(nèi)放不下新的物品為止;
(3)物品最終的選擇狀態(tài)存儲到一維數(shù)組result中,背包內(nèi)物品的最大價值存儲到maxvalue中。
上述“物品單位價值最大優(yōu)先”的貪心算法(greedy)的偽代碼描述如下:
算法1:貪心算法greedy。
1.maxvalue←0
2.fori
=1 ton
do3.index[i
]←i
;4.sort[i
]←v
[i
]÷w
[i
];5.fori
=1 ton
do6.forj
=1 ton
-i
do7.if sort[j
]j
]?sort[j
+1];9.index[j
]?index[j
+1];10.fori
=1 ton
do11.if w[index[i
]]≤C then12.x
[index[i
]]←1;13.C
←C
-w[index[i
]];14.else
15.break;
16.fori
=1 ton
do17.maxvalue←maxvalue+x
[i
]*v
[i
];18.result[i
]←x
[i
];19.return maxvalue
算法1的時間復(fù)雜度主要由排序算法決定。由于經(jīng)典冒泡排序算法的時間復(fù)雜度為O
(n
),貪心選擇(代碼10到15行)的時間復(fù)雜度為O
(n
),故算法1的時間復(fù)雜度為O
(n
),其中n
為物品的數(shù)量。若將排序算法改為快速排序算法,可以將該算法的時間復(fù)雜度降低為O
(n
logn
)。與貪心算法相比,經(jīng)典回溯算法更看重問題的整體性分析。經(jīng)典回溯算法是使用深度優(yōu)先遍歷求解0-1背包問題的經(jīng)典算法。在問題求解的過程中,回溯算法將物品的選擇狀態(tài)構(gòu)造成一個解空間樹,通過遍歷解空間樹中的每個節(jié)點來尋找問題的可行解和最優(yōu)解。具體地說,經(jīng)典的回溯算法從解空間樹的根節(jié)點出發(fā),依次判斷解空間樹的每一個節(jié)點,并選擇當(dāng)前狀態(tài)下滿足問題約束條件的節(jié)點,當(dāng)遍歷到葉子節(jié)點時,算法對當(dāng)前各個節(jié)點的選擇狀態(tài)進(jìn)行記錄和判斷,當(dāng)約束條件不滿足時,回退一步至上一狀態(tài)或回退多步,直至遍歷過解空間樹的每一個節(jié)點并回溯到根。在搜索的過程中,回溯算法會不斷判斷是否存在更優(yōu)的解,并記錄和更新目前已找到的最優(yōu)解。
經(jīng)典回溯算法解決0-1背包問題的主要步驟如下:
(1)構(gòu)造問題的解空間樹;
(2)確定問題的約束條件。一個是放入背包的物品總重量不超過背包的容量,另一個是放入背包的物品是否構(gòu)成問題的最優(yōu)解;
(3)從根節(jié)點開始,深度優(yōu)先遍歷解空間樹,在遍歷的過程中根據(jù)問題的約束條件選擇性地進(jìn)行回溯和繼續(xù)遍歷。
在使用經(jīng)典回溯算法解決0-1背包問題時,最壞情況下需要遍歷整個解空間樹,此時算法的時間復(fù)雜度為O
(2)。但一般情況下,回溯算法總會在遍歷到解空間樹的最后一個節(jié)點前找到問題的解,在實際的遍歷過程中,算法的運行時間取決于遍歷時生成的節(jié)點數(shù)目,即在找到問題的最優(yōu)解時,算法所遍歷到的節(jié)點數(shù)目。1.3.1 遞歸回溯算法
存在兩種實現(xiàn)經(jīng)典回溯的算法,一個是遞歸算法,一個是非遞歸算法。遞歸回溯算法,是指把一個大型的復(fù)雜問題分解為一個與原問題相似的、規(guī)模較小的問題,通過遞歸求解小問題并將子問題的解合并,從而得到原問題的解。
算法2給出了遞歸回溯算法(knap1)的偽代碼描述,該算法從位于解空間樹根節(jié)點的第1個物品開始遍歷,依次考慮當(dāng)前選中物品不放入背包和放入背包時,所有物品的選擇狀態(tài)。當(dāng)遍歷到葉子節(jié)點時,進(jìn)行最優(yōu)解的約束條件檢驗并判斷是否進(jìn)行回溯,算法的主要步驟如下:
(1)引入cw和cv分別表示當(dāng)前狀態(tài)下背包內(nèi)物品的總重量和總價值;
(2)對于每一個物品,首先選擇“不裝入背包”并進(jìn)行遞歸,而在進(jìn)行“裝入背包”的選擇前,則需要判斷所有選中物品的總重量是否滿足背包的容量;
(3)當(dāng)遍歷到最后一個物品時,計算此時背包內(nèi)物品的總價值,判斷是否為問題的最優(yōu)解。
算法2:遞歸回溯算法knap1。
Initialize maxvalue, cw, cv as 0
knap1(1)
output maxvalue
intknap1(int i)
if i=n+1 then
if cv>maxvalue then
maxvalue←cv;
result←x;
else
x[i]←0;
knap1(i+1);
if cw+w[i]≤C then
x[i]←1;
cv←cv+v[i], cw←cw+w[i];
knap1(i+1);
x[i]←0;
cv←cv-v[i], cw←cw-w[i];
returnmaxvalue
1.3.2 非遞歸回溯算法
與遞歸回溯算法不同,非遞歸回溯算法利用物品的狀態(tài)值判斷是否需要回溯,而不需要借助操作系統(tǒng)提供的遞歸機制,因而一般具有較高的時空效率。
算法3給出了非遞歸回溯算法(knap2)的偽代碼描述,在該算法中,選中物品在進(jìn)行“裝入”或“不裝入”背包的選擇前,其狀態(tài)值首先會被賦值為-1(代碼第2行);當(dāng)物品的選擇狀態(tài)確定后,其狀態(tài)值則為0或1(代碼第4、15行);一旦該物品的狀態(tài)值增加至2時,則需要進(jìn)行回溯(代碼第17、18行)。
算法3:非遞歸回溯算法knap2。
1.Initialize maxvalue as 0,i
as 12.x
[i
]←-13.whilei
≥1 do4.x
[i
]++;5.ifx
[i
]≤1 then6.ifi
=n
then7.forj
=1 ton
do8.cw←cw+x
[j
]*w
[j
];9.cv←cv+x
[j
]*v
[j
];10.if cw≤C and cv>maxvalue then
11.maxvalue←cv;
12.result←x;
13.cw←0, cv←0;
14.else
15.i
++;16.x
[i
]←-1;17.else
18.i
--;19.end
20.return maxvalue
使用貪心算法求解0-1背包問題時,算法從問題的某一初始解出發(fā),選擇當(dāng)前條件下的最優(yōu)解,并試圖構(gòu)造或逼近問題的整體最優(yōu)解。貪心算法每一步的決策僅考慮當(dāng)前的局部信息,其解空間不可回溯再現(xiàn),具有較強的隨機性和不可預(yù)知性。這種基于經(jīng)驗或直覺的判斷,并不一定能夠保證找到問題真正的最優(yōu)解,在絕大多數(shù)情況下,貪心算法得到的解只是問題的近似最優(yōu)解。但是,由于貪心算法采用局部最優(yōu)決策,因而往往具有較高的效率。
回溯算法的思想和枚舉法類似,即通過嘗試問題所有可能的解來尋找問題的最優(yōu)解,這種算法雖然確保了解的正確性,但是以犧牲算法運行時間為代價。當(dāng)問題規(guī)模較大時,回溯算法的運行時間呈指數(shù)式增長,在短時間內(nèi)可能無法得到問題的最優(yōu)解。
針對上述特征,該文將貪心算法的高效性和回溯算法的最優(yōu)性相結(jié)合,提出了一種融合貪心策略和剪枝策略的新型回溯算法,簡稱新型算法??紤]到貪心算法得到的解雖然可能不是問題的最優(yōu)解,但至少一定是問題的近似解,故將其作為初始解應(yīng)用于回溯算法,從而可以盡快實現(xiàn)剪枝操作,進(jìn)而提高回溯算法效率。
因此,新型算法將貪心算法的解作為回溯算法中剪枝策略的判斷條件,同時優(yōu)化了遍歷過程中的約束條件,從而在確保得到問題最優(yōu)解的同時,可以進(jìn)一步提高算法效率。
算法4給出了所提出的新型算法的偽代碼描述。該算法使用遞歸方法求解0-1背包問題,與經(jīng)典的回溯算法不同,首先,算法4增加了基于價值的剪枝策略,若背包內(nèi)物品的總價值與未遍歷到的物品的總價值之和小于算法1得到的解,則進(jìn)行剪枝并回溯。其次,在遍歷的過程中,算法4優(yōu)化了物品選擇的約束條件,將經(jīng)典回溯算法的約束條件“放入背包的物品總重量不超過背包的容量”修改為“當(dāng)前選中的物品重量滿足背包的剩余容量”。
所提出新型算法的主要步驟如下:
(1)引入pw和pv分別表示前i
-1個物品中,已經(jīng)放入背包的物品的總重量和總價值,rw表示背包的剩余容量,rv表示未遍歷到的物品的總價值(包含當(dāng)前物品);(2)算法1得到的解存儲到maxvalue_greedy中;
(3)定義遞歸函數(shù)GB(i
, rw, pw, rv, pv),從初始狀態(tài)GB(1,C
, 0, totalvalue, 0)開始遞歸;(4)首先判斷選中物品“不裝入背包”時是否需要剪枝;
(5)若選中物品“裝入背包”,首先判斷物品重量是否滿足背包的剩余容量,若“能裝入”,則繼續(xù)進(jìn)行步驟4的剪枝判斷,最終確定物品的選擇狀態(tài)。
算法4:新型算法。
1.Initialize maxvalue, pw, pv as 0, rw asC
, rv as totalvalue,i
as 12.maxvalue_greedy←greedy()
3.GB(1,C
, 0, totalvalue, 0)4.output maxvalue
int GB(inti
, int rw, int pw, int rv, int pv)1.ifi
=n
+1 then2.fori
ton
do3.value←cv+v
[i
]*x
[i
];4.if value>maxvalue then
5.maxvalue←value;
6.result←x;
7.else
8.if pv+rv-v
[i
]>maxvalue_greedy then9.GB(i
+1, rw, pw, rv-v
[i
], pv);10.ifw
[i
]≤rw then11.if pv+rv>maxvalue_greedy then
12.x
[i
]←1;13.GB(i
+1, rw-w[i
], pw+w
[i
], rv-v
[i
], pv+v
[i
]);14.x
[i
]←0;15.return maxvalue
在新型算法中,遞歸函數(shù)GB(第3行)的含義是:若當(dāng)前考慮的物品“不裝入背包”,計算此時背包內(nèi)物品的總價值與未遍歷到的物品的總價值之和,若大于maxvalue_greedy,則表明,在當(dāng)前物品的選擇狀態(tài)下,存在將某些物品裝入背包后使得總價值提高的可能,因此進(jìn)行遞歸;否則,表明在當(dāng)前物品的選擇狀態(tài)下,任何后續(xù)的裝入選擇都將不可能超過現(xiàn)在背包內(nèi)物品的總價值,此時則進(jìn)行剪枝并回溯。若當(dāng)前選中物品想要“裝入背包”,首先判斷該物品的重量是否滿足背包的剩余容量,然后繼續(xù)判斷是否“有必要裝入”。當(dāng)遍歷到最后一個物品時,計算此時背包內(nèi)物品的總價值并判斷是否為問題的最優(yōu)解。
新型算法的核心思想是:對于每一個物品,只有該物品“能裝入背包”且“有必要裝入”,才會將其放入背包中。
該文進(jìn)行了大量的仿真實驗,具體實驗環(huán)境為:CPU:i7-8550U,內(nèi)存:DDR2 16 GB;硬盤:1 TB;緩存,8 MB;PF使用率:36%~45%;編程語言:Java,軟件開發(fā)工具:Eclipse。分別實現(xiàn)了遞歸回溯算法(算法2)、非遞歸回溯算法(算法3)和新型算法(算法4),并在不同問題規(guī)模下進(jìn)行仿真實驗與分析。
實驗參數(shù)設(shè)置如下:根據(jù)物品數(shù)量n
,算法按照均勻分布隨機地產(chǎn)生1~20之間的整數(shù)作為每個物品的重量和價值,背包容量為物品總重量與一個預(yù)先定義的實驗系數(shù)f
之積,其中,f
為一個0到1之間的小數(shù),f
越小,表示背包的容量越小。f
為0.3、0.6、0.8,在不同問題規(guī)模n
下,使用遞歸回溯算法(算法2)、非遞歸回溯算法(算法3)和新型算法(算法4)得到問題最優(yōu)解時的時間耗費進(jìn)行實驗。實驗結(jié)果依次見表1~表3。表1 三種算法在實驗系數(shù)f=0.3的時間耗費
表2 三種算法在實驗系數(shù)f=0.6的時間耗費
表3 三種算法在實驗系數(shù)f=0.8的時間耗費
通過上述比較,可以得出以下結(jié)論:
(1)在不同實驗系數(shù)下,隨著問題規(guī)模的增加,所有算法的時間耗費都呈現(xiàn)上升趨勢,其中經(jīng)典的遞歸回溯算法和非遞歸回溯算法的上升趨勢更為顯著。結(jié)合算法的時間復(fù)雜度可知,經(jīng)典回溯算法的時間耗費隨著問題規(guī)模的增加呈指數(shù)級增長。此外發(fā)現(xiàn),非遞歸回溯算法較遞歸回溯算法具有較高的運行時間。
(2)在同一實驗系數(shù)、同一問題規(guī)模下,與經(jīng)典回溯算法相比,該文所提出的新型算法在保證得到問題的最優(yōu)解的同時,具有較小的時間耗費,特別是在問題規(guī)模較大時,效果更為明顯。
在不同實驗系數(shù)下,對遞歸回溯算法(算法2)和非遞歸回溯算法(算法3)的時間耗費進(jìn)行了對比,從而驗證實驗系數(shù)是否對經(jīng)典回溯算法的執(zhí)行時間產(chǎn)生影響。實驗結(jié)果見表4。
表4 經(jīng)典回溯算法在問題規(guī)模n=20時的時間耗費
根據(jù)表4可知,當(dāng)實驗系數(shù)從0.3逐漸增加至0.9時,遞歸回溯算法的時間耗費線性增長至某一數(shù)值后,在該數(shù)值處呈現(xiàn)小幅度波動;非遞歸回溯算法的時間耗費則始終在某數(shù)值處小幅度波動。
從表中可知,當(dāng)實驗系數(shù)增大至0.7時,兩種回溯算法的時間耗費都基本保持穩(wěn)定,故取實驗系數(shù)f
=0.8,單獨對新型算法進(jìn)行實驗,分析其算法運行時間與問題規(guī)模間的關(guān)系。實驗結(jié)果如圖1所示。圖1 新型算法的時間耗費(f=0.8)
從圖1可以看出,在實驗系數(shù)為0.8時,只有當(dāng)問題規(guī)模近似增加至70時,新型算法的時間耗費才會有較為明顯的遞增,效率遠(yuǎn)遠(yuǎn)高于經(jīng)典回溯算法。
表5列出了在不同的實驗系數(shù)和不同的問題規(guī)模下,新型算法得到問題最優(yōu)解的時間耗費情況。從表5中可知,新型算法普遍隨實驗系數(shù)的增加而減少,其原因在于,隨著實驗系數(shù)的增加,背包的容量不斷增大,背包可以容納的物品數(shù)量相應(yīng)增加,從而減少了回溯的概率,進(jìn)而提高了算法效率。
表5 新型算法在不同實驗系數(shù)、不同問題規(guī)模下的時間耗費
0-1背包問題是經(jīng)典的NP完全問題,而經(jīng)典的回溯算法采用枚舉的思想,通過深度優(yōu)先搜索解空間樹尋找問題的最優(yōu)解。在問題規(guī)模較小時,回溯算法同其他求解0-1背包問題的經(jīng)典算法相比,具有更小的時間耗費和空間耗費。但隨著問題規(guī)模的增加,回溯算法在時間和空間上都有極為明顯的增加,這種增加導(dǎo)致算法在較短時間內(nèi)無法得到問題的最優(yōu)解。
該文將貪心算法的高效性和經(jīng)典回溯算法的最優(yōu)性相結(jié)合,提出的融合貪心策略與剪枝策略的新型算法,將經(jīng)典貪心算法得到的問題近似解用于剪枝策略的判斷條件中,減少了經(jīng)典回溯算法遍歷過程中的無效搜索;同時,在進(jìn)行物品選擇的判斷時,使用背包剩余容量作為約束條件,大大提高了算法的求解效率。大量仿真實驗結(jié)果表明,該新型算法在保證得到問題最優(yōu)解的同時,有效提高了算法的運行效率。