背包問題(Knapsack problem)是一個動態規划問題,假設有n種貨物,每種貨物的的價值是v[i],重量是w[i],需要在背包負載有限的前提下求出具有最大貨值的組合(策略),使用暴力算法也可以求出背包問題最優解,而利用動態規划可以將算法的復雜度降至接近於多項式復雜度,背包問題根據每種貨物的數量限制可分為以下幾種:
0-1背包問題:每種貨物數量1件,選擇每種貨物的策略是取(1)還是不取(0)。
完全背包問題:每種貨物數量有無限個,最終的策略是每種貨物取多少件。
多重背包問題:每種貨物的數量為有限個,但各種貨物數量不一樣,比如第i種貨物的數量為a[i]件。
解決了完全背包問題后,通過引入數量的判斷條件,就可解決其他兩種背包問題。介紹背包問題算法之前先來了解一些動態規划的相關知識及術語。
一、動態規划
1.1、概念介紹
線性規划為靜態規划,而動態規划顯著的特點是問題有階段性,以下面的最短路線問題為例:
上圖中圈號代表具體的地址結點,兩個結點間連線代表兩地距離,最短路線問題需要求出,從出發點A到目的地E哪條路徑最短。上圖到達目的地可分為四個階段,A出發選B1或B2為第一階段,從Bi到Ci為第二階段,Ci到Di為第三個階段,Di到E為第四個階段;圈內字母代表狀態,每個階段初始狀態集合稱為該階段的狀態,例如第一階段狀態S1={A},第二階段狀態S2={B1,B2},第三階段狀態S3={C1,C2,C3},第四階段狀態S4={D1,D2},每個階段向下一個階段前進時,面臨着多種選擇,如第一階段向第二階段變化時可選擇A到B1或A到B2,每一種選擇稱為決策,決策產生新的狀態用小寫s表示,而每個階段決策用小寫u表示,例如選擇從A到B1則有s2=B1,而選擇從A到B2則有s2=B2,狀態sk選擇具體的決策uk后,下個階段k+1狀態往往是能確定的,稱sk+1=T(sk,uk)為狀態轉移方程。從A到E每個階段選擇不同的決策構成一個狀態序列p1,n(s1)稱為策略,從k階段開始策略稱為子策略用pk,n(sk)表示,顯而易見,從出發點A到目的地E有許多種策略。
以上介紹了動態規划中狀態、決策、狀態轉移方程、策略的概念,接下來再看與策略優化相關的概念,對於最短路線問題而言,最優的策略顯然要求各個階段路程之和最小。假設在k階段狀態為sk,采用了決策uk后得到k+1階段的狀態sk+1,用一個階段指標函數來量化決策uk,例如從A到B1節點有:
與此類似,如決策采用A到B2節點則有:
假設k階段狀態為sk,采取策略pk,n(sk)產生的一系列階段函數之和稱為指標函數:,具體形式為:
從k階段的狀態sk到最終狀態sn有許多策略可用,就最短路線問題而言,最優的策略顯然是指標函數值最小的策略,引入最優指標函數fk(sk):
動態規划問題歸結為求解最優指標函數f1(s1),得到f1(s1)后即可得到最優策略。
1.2、逆推法
求解動態規划常用方法有逆推法和順推法,設動態規划問題一共有n個階段,逆推法從n階段向前逆向推導每個階段的最優決策,直至推導出最優指標函數f1(s1),然后利用已推導的最優決策,從開始階段順次得到各個階段最優狀態。以開頭最短路線問題為例:
從E點出發即k=4時:
針對D1有指標函數f4(D1)=8,狀態轉移方程E=T(D1,u4(D1)),針對D2有f4(D2)=4,狀態轉移方程E=T(D2,u4(D2))。
k=3時:
f3(C1)=min{6+f4(D1),5+f4(D2)}=min{6+8,5+4}=9,從C1出發到下個階段最優決策是選擇D2,記u3(C1)=D2,在確保最短短路程的前提下,有狀態轉移方程D2=T(C1,u3(C1))。
f3(C2)=min{2+f4(D1),3+f4(D2)}=min{2+8,3+4}=7,記u3(C2)=D2。
f3(C3)=min{8+f4(D1),5+f4(D2)}=min{8+8,5+4}=9,記u3(C3)=D2。
k=2時:
f2(B1)=min{2+f3(C1),3+f3(C2)}=min{2+9,3+7}=10,記u2(B1)=C2。
f2(B2)=min{4+f3(C1),5+f3(C3)}=min{4+9,5+9}=13,記u2(B1)=C1。
k=1時:
f1(A)=min{5+f2(B1),3+f2(B2)}=min{5+10,3+13}=15,記u1(A)=B1
得到最優指標函數f1(A)后即得到了問題最優值,接下來再從A出發,利用每個階段的最優決策求出每個階段的狀態:
k=1時,由u1(A)=B1,確定路線A到B1。
k=2時,由u2(B1)=C2,確定路線B1到C2。
k=3時,由u3(C2)=D2,確定路線C2到D2。
k=4時,由u4(D2)=E,確定路線D2到E。
綜上所述,該動態規划最優路線為A→B1→C2→D2→E。
1.3、順推法
順推法顧名思義是從k=1階段開始順序推導至k=n階段,首先引入一個新的最優指標函數:
上式中k表示第k階段結束狀態為sk+1時最優函數。以上圖為例,C1同時連接B1和B2,B1、B2是第一階段結束狀態可選集合,同時B1、B2又是第二階段開始狀態集合;而C1屬於第三階段的狀態同時也是第二階段結束狀態之一。根據定義有:f2(C1)=min{2+f1(B1),4+f1(B2)},逆推法的最優指標函數以開始狀態作為標識,而順推法的最優指標函數以結束狀態作為標識,選擇的標識不同是因兩者算法差異造成的,
用公式可表達為:
①
①式中sk是一個變量,sk+1是一個定值,表示狀態sk與sk+1之間的階段指標函數,
表達的是一個集合,公式中含義可根據f2(C1)的表達式對號入座來理解,特別的,設初始狀態f0(s1)=0。順推法求解上面最短路線問題即為求解最優指標函數f4(E),接下來用順推法解決之前的最短路線問題。
k=1時,有
f1(B1)=5,u1(B1)=A;f1(B2)=3,u1(B2)=A
k=2時,有
f2(C1)=min{2+f1(B1),4+f1(B2)}=min{2+5,4+3}=7,u2(C1)=B1或B2
f2(C2)=min{3+f1(B1)}=8,u2(C2)=B1
f2(C3)=min{5+f1(B1)}=8,u2(C3)=B2
k=3時,有
f3(D1)=min{6+f2(C1),2+f2(C2),8+f2(C3)}=min{6+7,2+8,8+8}=10
u3(D1)=C2
f3(D2)=min{5+f2(C1),3+f2(C2),5+f2(C3)}=min{7+7,3+8,7+8}=10
u3(D2)=C2
k=4時
f4(E)=min{8+f3(D1), 4+f3(D2)}=min{8+10,4+11}=15,u4(E)=D2
注意到順推法得到的最優指標函數f4(E)等於逆推法得到f1(A),這是很容易理解的,A到E等效於E到A,而由決策序列:
u4(E)=D2 ,u3(D2)=C2 ,u2(C2)=B1 ,u1(B1)=A
可知最優策略為A→B1→C2→D2→E。
可根據目標最優指標函數來區分使用的是逆推法還是順推法,如目標函數是形式f1(A),即以初始狀態和初始階段為最優指標函數標識符的,使用的是逆推法;而類似f4(E)以最終階段和最終狀態為函數標識符的是順推法。
二、動態規划解決背包問題
2.1、完全背包問題
前面介紹過,完全背包問題指的是每種貨物數量不限,以下面這個問題為例,假設一輛汽車最多可運7噸貨物,有甲、乙、丙三種物資,每種物資貨值及重量如下表:
要求出在規定核載噸位下最大貨值的組合。
上述問題可轉化為下面的動態規划問題:
x1,x2,x3都是件數、皆為整數。對物資甲、乙、丙分三階段分配數量,起始狀態s1≤7代表待分配噸位不大於7噸,x1,x2,x3件數作為決策變量,分配完物資甲后第二階段初始狀態s2=s1-x1,與此類似,分配完物資乙后第三階段狀態s3=s2-2x2,分配完丙后s4=s3-3x3=0,有了狀態轉移方程之后引入最優指標函數fk(s),其意義指在裝載能力不大於s的前提下,k階段到最后第3階段的最大貨值,顯然f1(7)的值即為所求的最大貨值,由目標最優指標函數形式可知,將使用逆推法求解該問題,f1(7)表達式為:
f1(7)中根據狀態轉移方程s2=s1-x1確定了第二階段可分配重量,接下來逐個分析其中多項式,以f2(7)為例,f2(7)代表在第一階段貨物甲分配了0件:
f2(6)代表第一階段甲分配了1件
依次可得下列公式
f3(s3)代表第三階段對貨物丙進行分配,如f3(7)代表甲、乙都沒有分配,留給貨物丙的配載能力是7噸
f3(6)代表第三階段可分配重量為6噸
相應的可得到第三階段其他的指標函數
接下來就是逆推過程了,將f3(s3)各個值代入f2(s2)各個表達式中:
f2(s2)各個值代入f1(7)中有:
如此就得到了最大貨物價值為18,再來看最優策略的產生:
x1=1時即甲為1件時,對應於第二階段f2(6):
從指標函數可以看出第二階段最優決策是x2=0,由狀態方程s3=s2-2x2知,s3=6,f3(6)表達式為:
綜上所述最優策略為x1=1,x2=0,x3=2,即甲1件,乙0件,丙2件。
另外一個最優策略是當x1=0時,此時f2(7):
第二階段最優決策為x2=2,由狀態方程s3=s2-2x2知,s3=7-4,f3(3)表達式為
另一個最優策略為x1=0,x2=2,x3=1,即甲0件,乙2件,丙1件.
將上述分析利用代碼實現如下:
余下文章請轉至鏈接: