背包問題解析(二)-遞歸算法


一、題目:
有N件物品和一個容量為V的背包。第i件物品的重量是w[i],價值是v[i]。求解將哪些物品裝入背包可使這些物品的重量總和不超過背包容量,且價值總和最大。
 
二、遞歸方法:
首先對於每個物品,我們的選擇只有兩個:放或者不放。我們將所有的可能都窮舉出來,就可以得到下面這個樹狀圖(只畫了前四個結點):
 
所以對於每一個子問題,由於前面的子問題已被解決,因此我們都只需要做兩個選擇:放,還是不放。
假設我們已經知道了前i−1個物品放入背包的最優方案F(i−1,v i−1 ),那么對於第i個物品要放入背包就有三種情況:
1、若物品的體積c i  大於背包剩余的容量v i−1  ,那么只能丟棄這個物品:
F(i,vi)=F(i−1,vi−1)
2、否則就有兩種選擇:
(1)、不放第i個物品:
F(i,vi)=F(i−1,vi−1)
(2)、放第i個物品:
F(i,vi)=wi+F(i−1,vi−1−ci)
要從這兩個方案中選擇總價值最大的,所以:
 
三、python代碼實現如下:
def rec_bag(c, w, v, i=0):
'''
param c: 物品體積
param w: 物品價值
param v: 當前背包剩余容量
param i: 當前物品編號
return: 背包裝下物品的最大價值
'''
if i > len(c)-1:
return 0
elif v <= 0: #體積不能為負
return 0
elif v > 0:
if c[i] <= v:
A = w[i] + rec_bag(c, w, v-c[i], i+1)
B = rec_bag(c, w, v, i+1)
res = max(A, B)#兩種方案中選最優的那個並返回
else:
res = rec_bag(c, w, v, i+1)#物品體積大於背包容量,直接返回
return res
 
a=rec_bag([2,3,4,5],[3,4,5,6],8,0)
print(a)
 
 
四、算法分析:
遞歸方法最大的缺點就在於有較多重復的計算,通過上面的樹狀圖可以知道,遞歸會遍歷這棵樹的所有結點,所以它的時間復雜度為:O(2 n )
O(2n),指數階的時間復雜度對於計算機來說簡直就是災難!
有沒有什么辦法減少這些重復的計算呢?這就是接下來要說的動態規划,它可以通過存儲已經計算出來的結果來減少重疊子問題。
 
 


免責聲明!

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



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