RQNOJ 329 二維揹包 順便收集整理一下相關資料

今天做這題,wa了很多次。原來是01揹包沒學好。

以下是優化空間複雜度後的程序

以下是最直觀的01揹包

 

一般情況

 procedure Make;
  begin
  for i:=0 to w do
  f[0,i]:=0;
  for i:=1 to m do
  for j:=0 to w do begin
  f[i,j]:=f[i-1,j];                                                  //這語句很重要!! 
  if (j>=w) and (f[i-1,j-w]+v>f[i,j]) then
  f[i,j]:=f[i-1,j-w]+v;
  end;
  writeln(f[m,wt]);
  end;

 

優化空間複雜度
  以上方法的時間和空間複雜度均爲O(N*V),其中時間複雜度基本已經不能再優化了,但空間複雜度卻可以優化到O(V)。
  先考慮上面講的基本思路如何實現,肯定是有一個主循環i=1..N,每次算出來二維數組f[0..V]的所有值。那麼,如果只用一個數組f[0..V],能不能保證第i次循環結束後f[v]中表示的就是我們定義的狀態f[v]呢?f[v]是由f[v]和f[v-c]兩個子問題遞推而來,能否保證在推f[v]時(也即在第i次主循環中推f[v]時)能夠得到f[v]和f[v-c]的值呢?事實上,這要求在每次主循環中我們以v=V..0的順序推f[v],這樣才能保證推f[v]時f[v-c]保存的是狀態f[v-c]的值。僞代碼如下:
  for i=1..N
  for v=V..0
  f[v]=max{f[v],f[v-c]+w};

 

 初始化的細節問題
  我們看到的求最優解的揹包問題題目中,事實上有兩種不太相同的問法。有的題目要求“恰好裝滿揹包”時的最優解,有的題目則並沒有要求必須把揹包裝滿。一種區別這兩種問法的實現方法是在初始化的時候有所不同。
  如果是第一種問法,要求恰好裝滿揹包,那麼在初始化時除了f[0]爲0其它f[1..V]均設爲-∞,這樣就可以保證最終得到的f[N]是一種恰好裝滿揹包的最優解。
  如果並沒有要求必須把揹包裝滿,而是隻希望價格儘量大,初始化時應該將f[0..V]全部設爲0。
  爲什麼呢?可以這樣理解:初始化的f數組事實上就是在沒有任何物品可以放入揹包時的合法狀態。如果要求揹包恰好裝滿,那麼此時只有容量爲0的揹包可能被價值爲0的nothing“恰好裝滿”,其它容量的揹包均沒有合法的解,屬於未定義的狀態,它們的值就都應該是-∞了。如果揹包並非必須被裝滿,那麼任何容量的揹包都有一個合法解“什麼都不裝”,這個解的價值爲0,所以初始時狀態的值也就全部爲0了。
  這個小技巧完全可以推廣到其它類型的揹包問題,後面也就不再對進行狀態轉移之前的初始化進行講解。

 

完全揹包問題

最優解法—O(VN)
  for i=1..N
  for j=0..V
  f[j]=max{f[j],f[j-c]+w}
這個僞代碼與01揹包的僞代碼只有v的循環次序不同而已。

 

部分內容摘自百度百科

發佈了20 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章