對於01揹包,用二維數組做DP的情況如下:
F[i,v]代表,在揹包容量爲v的情況下,從前i件物品中選出若干件(因揹包容量的限制,可能不會所有i件都在裏面,取最大值時揹包裏應該是權值相對較大的那些物品)所能得到的最大價值。
第一句對dp設置初始條件。
兩個for循環遍歷所有的情況:i從1~N表示從i件物品中選取,v從ci~V表示揹包的大小(現在考慮的是第i件物品的放與不放,因此揹包應該至少大於等於i物品的費用,否則無意義)
最關鍵的問題在於max{F[i-1,v],F[i-1,v-Ci]+wi}這一句
F[i-1,v]表示在揹包容量v的情況下,從前i-1個物品中怎樣放置使價值最大,這也代表,對於第i件物品,我們不選擇將它放入揹包,而去從前i-1個物品中選擇放置策略,但這與F[i-1,v-Ci]是不同的,因爲我們現在只是選擇不把這個i放進去,而不代表我們要削減揹包的容量。
F[i-1,v-Ci]+wi表示,在揹包容量爲v的情況下,我們選擇將這個第i件物品放入揹包的情況。此時F[i,v]應該是,在放入之前揹包的最大價值,加上放入之後的最大價值。而放入之前揹包的最大價值爲F[i-1,v-Ci]。
仔細思考F[i-1,v]與F[i-1,v-Ci]的區別:
現在我們計算的是F[i,v],也就是說揹包的容量已經定死爲v了,F[i-1,v]是因爲我們放棄了將i加入揹包,揹包的容量是不變的。而F[i-1,v-Ci]是因爲,現在我們選擇將i加入揹包,也就是說,這個揹包至少已經有一個i了,這個i的容量也爲Ci了,而揹包總共爲v,現在要計算它的最大價值,就要加上在v-Ci中,在前i-1個物品中做選擇使揹包容量最大的值了。
這個方法使用的是二維數組,而實際上,i時刻的結果只與i-1時刻下的策略有關。
我們考慮用一個一維數組來進行dp。
對於一維數組來說,它無法保存兩個狀態i與v,但是,由於i只與i-1有關,因此如果我們逐步更新i,在i時刻進行放置之前,F[v]實際上保存的就是i-1下的最優值,而更新後直到i+1時刻的放置策略之前,F[v]都保存的是i下的最優值。
因此:
首先解釋下max{F[v],F[v-Ci]+Wi}:
我們已經明確了,F[v]表示的是i下的最優值。
而在i下,在進行到F[v]=max{F[v],F[v-Ci]+Wi};之前,我們看F[v],這個時候的F[v]實際上是保存的是i-1下揹包容量爲v的最優值,因此:
在對F[v]賦值之前,F[v]表示,不考慮第i件物品,只考慮前i-1個物品的情況下,在揹包容量爲v下的最優解。
而F[v-Ci]表示,在i-1下,揹包容量爲v-Ci的最優解,再加上右邊的Wi,就表示一定將i放入揹包的情況。
在解釋下關於逆序的問題:
從上面可以看到,對v來說,它是從V遞減到Ci的,而且一定只能是逆序,這是因爲:
從內循環來說,每一次內循環,都相當於更新在i下,揹包容量爲v最優解。更新之前,F[v]表示i-1下的最優解,而一旦賦值結束,F[v]就表示i下的最優解了。
如果爲順序,當我們進行到F[v]時,要使用到F[v-Ci],但是這個F[v-Ci]必須是i-1下的最優解,而由於順序的原因,在我們將v遞增到(順序的情況下)v時,已經經歷了v-Ci這個揹包容量了,換句話說,此時v下的F[v-Ci],已經代表的是i下揹包容量爲v-Ci的最優解了,而我們需要的是i-1下,揹包容量爲v-Ci的最優解!
因此,我們必須要使用逆序,這樣當進行到v時,F[v-Ci]還未更新,它還依然表示i-1下的最優解。