動態規劃 01揹包問題 續

2022-02-09 04:33:04 字數 3294 閱讀 4676

這段時間每天加班,確實沒有整塊的時間來寫部落格了,一不小心就到週末了,要是不寫篇部落格,那就又要鴿了。為了不打臉,還是加班加點的把這篇部落格給寫了出來。

再說個題外話,最近一直在看一本關於mysql的掘金小冊,感覺很棒,作者用通俗易懂的語言將mysql的底層原理進行了介紹,**並茂,講解的很深入,可以看出作者應該是花了不少心思,借閱了不少書籍的。據說作者是個95後,為了寫這本小冊子還特意辭了職,簡直優秀!

好了,閒話就說到這了,言歸正傳。

已經過去乙個星期了,可能一部分人已經忘記了之前的解題思路,所以在這裡把之前填表法使用到的圖貼了過來:

再回頭看下之前的遞推關係式:

可以發現,每次求解ks(i,j)只與ks(i-1,m)有關。也就是說,如果我們知道了k(i-1,1...j)就肯定能求出ks(i,j),為了更直觀的理解,再畫一張圖:

下一層只需要根據上一層的結果即可推出答案,舉個栗子,看i=3,j=5時,在求這個子問題的最優解時,根據上述推導公式,ks(3,5) = max = max = 6;如果我們得到了i=2時所有子問題的解,那麼就很容易求出i=3時所有子問題的解。

因此,我們可以將求解空間進行優化,將二維陣列壓縮成一維陣列,此時,裝填轉移方程變為:

ks(j) = max
這裡ks(j - wi)就相當於原來的ks(i-1, j - wi)。需要注意的是,由於ks(j)是由它前面的ks(m)推導出來的,所以在第二輪迴圈掃瞄的時候應該由後往前進行計算,因為如果由前往後推導的話,前一次迴圈儲存下來的值可能會被修改,從而造成錯誤。

這麼說也許還是不太清楚,回頭看上面的圖,我們從i=2推算i=3的子問題的解時,此時一維陣列中存放的是,這是i=2時所有子問題的解,如果我們從前往後推算i=3時的解,比如,我們計算ks(0) = 0,ks(1) = ks(1) = 0(因為j=1時,裝不下第三個珠寶,第三個珠寶的重量為5),ks(2) = 2,ks(3) = 4,ks(4) = 4, ks(5) = max = 6,....,ks(8) = max = 7。在這裡計算ks(8)的時候,我們就把原來ks(8)的內容修改掉了,這樣,我們後續計算就無法找到這個位置的原值(這個栗子沒舉好。。因為後面的計算沒有用到ks(8)= =),也就是上一輪迴圈中計算出來的值了,所以在遍歷的時候,需要從後往前進行倒序遍歷。

public class solution;

int ws = ;

int newresults = new int[11];

@test

public void test()

private int ksp(int i, int c)

// 可以在這裡輸出中間結果

system.out.println(json.tojsonstring(newresults));

}return newresults[newresults.length - 1];}}

輸出如下:

[0,0,0,0,0,0,0,0,0,0,0]

[0,0,2,2,2,2,2,2,2,2,2]

[0,0,2,4,4,6,6,6,6,6,6]

[0,0,2,4,4,6,6,6,7,7,9]

[0,0,2,4,4,7,7,9,11,11,13]

13

這樣,我們就順利將空間複雜度從o(n*c)優化到了o(c)。當然,空間優化的代價是,我們只能知道最終的結果,但無法再回溯中間的選擇,也就是無法根據最終結果來找到我們要選的物品組合。

01揹包問題一般有兩種不同的問法,一種是「恰好裝滿揹包」的最優解,要求揹包必須裝滿,那麼在初始化的時候,除了ks(0)0,其他的ks(j)都應該設定為負無窮大,這樣就可以保證最終得到的ks(c)是恰好裝滿揹包的最優解。另一種問法不要求裝滿,而是只希望最終得到的價值盡可能大,那麼初始化的時候,應該將ks(0...c)全部設定為0

為什麼呢?因為初始化的陣列,實際上是在沒有任何物品可以放入揹包的情況下的合法狀態。如果要求揹包恰好裝滿,那麼此時只有容量為0的揹包可以在什麼都不裝且價值為0的情況下被「恰好裝滿」,其他容量的揹包均沒有合法的解,因此屬於未定義的狀態,應該設定為負無窮大。如果揹包不需要被裝滿,那麼任何容量的揹包都有合法解,那就是「什麼都不裝」。這個解的價值為0,所以初始狀態的值都是0。

01揹包問題可以用自上而下遞迴記憶法求解,也可以用自下而上填表法求解,而後者可以將二維陣列的解空間優化成一維陣列的解空間,從而實現空間複雜度的優化。

對於01揹包問題的兩種不同問法,實際上的區別便是初始值設定不一樣,解題思路是一樣的。

動態規劃揹包問題 01揹包

問題描述 n種物品,每種乙個。第i種物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包,使得揹包內物品不超過c的前提下,重量最大。問題分析 宣告乙個f n c 的陣列。f i j 表示把前i件物品都裝到容量為j的揹包所獲得的最大重量。當 j v i 時,揹包容量不足以放下第 i 件物品,f ...

動態規劃 揹包問題 01揹包

有n種物品和乙個容量為v的揹包,每種物品僅用一次。第i件物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使價值總和最大。例如 n 5,v 10 重量 價值 第乙個物品 10 5 第二個物品 1 4 第三個物品 2 3 第四個物品 3 2 第五個物品 4 1 首先我們考慮貪心策略,選取最大價...

0 1揹包問題(動態規劃)

一 問題描述 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。所謂01揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。二 解決方案 考慮使用動態規劃求解,定義乙個遞迴式 opt i v 表示前i個物品,在揹包容量大小為v的情況下,最...