揹包九講 01揹包的內迴圈逆序問題

2022-09-03 01:21:06 字數 1888 閱讀 4155

對於01揹包,用二維陣列做dp的情況如下:

f[i,v]代表,在揹包容量為v的情況下,從前i件物品中選出若干件(因揹包容量的限制,可能不會所有i件都在裡面,取最大值時揹包裡應該是權值相對較大的那些物品)所能得到的最大價值。

第一句對dp設定初始條件。

兩個for迴圈遍歷所有的情況:i從1~n表示從i件物品中選取,v從ci~v表示揹包的大小(現在考慮的是第i件物品的放與不放,因此揹包應該至少大於等於i物品的費用,否則無意義)

最關鍵的問題在於max這一句

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]表示的是i下的最優值。

而在i下,在進行到f[v]=max;之前,我們看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下的最優解。

揹包九講之 01揹包

01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...

揹包九講 01揹包問題

1 01揹包問題描述 已知 有 n 件物品和乙個容量為 v 的揹包。第i件物品的重量為w i 得到的價值是 c i 問題 求解將哪些物品裝入揹包可使價值總和最大。條件 每種物品只有一件,可以選擇放或者不放 2 基本思路 01揹包的特點 每種物品只有一件,可以選擇放或者不放 子問題定義狀態f i v ...

揹包九講專題 01揹包

樸素2維無優化寫法 includeusing namespace std const int maxn 1e3 5 int dp maxn maxn v maxn w maxn intmain printf d n dp n m view code 優化1維寫法 關於優化是怎麼來的?首先為什麼第二個...