本文實例講述了Python基于回溯法子集樹模板解決0-1背包問題。分享給大家供大家參考,具體如下:
問題
給定N個物品和一個背包。物品i的重量是Wi,其價值位Vi ,背包的容量為C。問應該如何選擇裝入背包的物品,使得放入背包的物品的總價值為最大?
分析
顯然,放入背包的物品,是N個物品的所有子集的其中之一。N個物品中每一個物品,都有選擇、不選擇兩種狀態(tài)。因此,只需要對每一個物品的這兩種狀態(tài)進行遍歷。
解是一個長度固定的N元0,1數組。
套用回溯法子集樹模板,做起來不要太爽!!!
代碼
'''0-1背包問題'''n = 3 # 物品數量c = 30 # 包的載重量w = [20, 15, 15] # 物品重量v = [45, 25, 25] # 物品價值maxw = 0 # 合條件的能裝載的最大重量maxv = 0 # 合條件的能裝載的最大價值bag = [0,0,0] # 一個解(n元0-1數組)長度固定為nbags = [] # 一組解bestbag = None # 最佳解# 沖突檢測def conflict(k): global bag, w, c # bag內的前k個物品已超重,則沖突 if sum([y[0] for y in filter(lambda x:x[1]==1, zip(w[:k+1], bag[:k+1]))]) > c: return True return False# 套用子集樹模板def backpack(k): # 到達第k個物品 global bag, maxv, maxw, bestbag if k==n: # 超出最后一個物品,判斷結果是否最優(yōu) cv = get_a_pack_value(bag) cw = get_a_pack_weight(bag) if cv > maxv : # 價值大的優(yōu)先 maxv = cv bestbag = bag[:] if cv == maxv and cw < maxw: # 價值相同,重量輕的優(yōu)先 maxw = cw bestbag = bag[:] else: for i in [1,0]: # 遍歷兩種狀態(tài) [選取1, 不選取0] bag[k] = i # 因為解的長度是固定的 if not conflict(k): # 剪枝 backpack(k+1)# 根據一個解bag,計算重量def get_a_pack_weight(bag): global w return sum([y[0] for y in filter(lambda x:x[1]==1, zip(w, bag))])# 根據一個解bag,計算價值def get_a_pack_value(bag): global v return sum([y[0] for y in filter(lambda x:x[1]==1, zip(v, bag))])# 測試backpack(0)print(bestbag, get_a_pack_value(bestbag))
效果圖

希望本文所述對大家Python程序設計有所幫助。
新聞熱點
疑難解答