01背包 完全背包 狀態轉移方程及空間復雜度優化


01 背包

問題描述:有N件【每件只有一個】物品和一個容量為V 的背包。第i 件物品的費用是w[i],價值是v[i],求將哪些物品裝入背包可使價值總和最大。

定義狀態:即f[i][j]表示前i件物品恰放入一個容量為j 的背包可以獲得的最大價值。

狀態轉移方程:

f[i][j]=max(f[i−1][j],f[i−1][j−w[i]]+v[i])

時間和空間復雜度均為O(VN)。時間復雜度不能再優化了,空間復雜度可以優化為O(N)

for (int i = 1; i <= n; i++) for (int j = V; j >= 0; j--) f[j] = max(f[j], f[j - w[i]] + v[i]);

注意:1:j是逆序   https://blog.csdn.net/yandaoqiusheng/article/details/84929357

   2 w[i]和v[i]中是i

可以進行優化的原因:每次寫入數據都是根據上一行的結果寫入的,數組一維就夠用了

其中的f[j]=max(f[j],f[j−w[i]]) 一句相當於轉移方程f[i][j]=max(f[i−1][j],f[i−1][j−w[i]]) ,因為現在的f[j−w[i]]就相當於原來的f[i−1][j−w[i]]。
注意上述代碼中利用了滾動數組原理

 

完全背包:

問題描述:有N種【每種有無數個】物品和一個容量為V的背包,每種物品都有無限件可用。第i種物品的費用是w[i],價值是v[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包容量,且價值總和最大。狀態轉移方程:

f[i][j]=max(f[i−1][j−k∗w[i]]+k∗v[i])∣0<=k∗w[i]<=j

注意:f[i−1],不是f[i]

狀態轉移方程含義:若k=0,f[i−1][j]即j費用全部取前i-1種物品;若k=1,f[i−1[j−w[i]]+v[i],即j-w[i]費用取前i-1種物品,w[i]費用取第i種物品。。。。。

 

優化為O(VN):

for (int i = 1; i <= n; i++)
    for (int j = w[i]; j <= V; j++)
      f(i,j)=
          f(i-1,j),如果不取第i件物品
          f(i,j-w(i))+v(i),如果取第i件物品

解釋一下,為什么一位數組中,不用寫k循環。[其他博客中均沒有詳細解釋這一點,我這里用自己的話來理解下】

假設不考慮f(i-1,j),如果不取第i件物品】這種情況

j=w(i)時,表示此次取一件i物品,f(i,0)+v(i)表示加上一件第i件物品的值,得到f(i,w(i))

j=2*w(i)時,由於滾動數組,f(i,w(i))已經是上一次的f(i,w(i)),已經加了一次w[i],所以這次只需再加一件w[i]即可。

...............

多次循環后,其實就等同於二維數組中的k循環了

 

 

寫成代碼:

for (int i = 1; i <= n; i++)
    for (int j = w[i]; j <= V; j++)
        f[j] = max(f[j], f[j - w[i]] + v[i]);

f[j]表示放入N種物品獲得的最大價值

注意:正序

 

參考文獻1

背包9講:https://blog.csdn.net/yandaoqiusheng/article/details/84782655

完全背包優化:https://blog.csdn.net/wumuzi520/article/details/7014830


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM