1. 程式人生 > >限界分支法(佇列方式)追蹤解:01揹包問題

限界分支法(佇列方式)追蹤解:01揹包問題

追蹤解

追蹤解,上述實現的情況下,解都在最後一層,根本不知道之前的路徑是怎樣的,廣度優先搜尋,同一個緯度,假如不加指標判斷的話,根本不知道最優解是選擇的哪一個,所以需要同一個緯度的每一個結點,記住他之前的路徑,才能在最優解的時候之前是怎麼走過來的,每一個結點用一個數組記錄路徑,這樣實現的感覺消耗有點大啊,通常看見是採用連結串列方式

限界分支法本質還是空間樹,樹的話,還是用連結串列實現比較容易和直觀

把之前實現基於陣列的形式修改成結點連結串列方式

實現如下:

#%%
# 修改成結點,為了追蹤解,新增兩個變數,是否選擇物品和前一個物品的結點
class Node:
    def
__init__(self, CurCost=None,CurValue=None,Flag=None,parent=None): # 部分解所佔體積 self.CurCost = CurCost # 部分解所佔價值 self.CurValue = CurValue # 當前結點是否選擇了物品 self.isleft = Flag # 前一個結點是誰 self.parent = parent class FIFO_01_Pack_with_solution_tracking
: def __init__(self,N,V,C,W): self.num =N self.Volume = V self.Cost = C self.Value = W # 存放最優解 self.BestResult = [False]*N # 最優解結點,這裡是葉子結點 self.BestNode = Node(0,0,False,None) #用於存放活結點,便於理解,把根結點,以及第0層結束標誌-1放進去 # 結點包括2個屬性:當前空間大小,當前的價值大小
self.queue = [Node(0,0,False,None),Node(-1,-1,False,None),] # 實現時葉子結點不加入到活結點列表,當屬於葉子結點時,增加對結果的處理 def enQueen(self,node,depth): if depth == self.num -1: CurValue = node.CurValue if CurValue > self.BestNode.CurValue: self.BestNode.CurValue = CurValue self.BestNode.isleft = node.isleft self.BestNode.parent = node.parent else: self.queue.append(node) def pack_01(self): # selected = [0]*self.num # 首先取出根結點 depth = 0 node = self.queue.pop(0) CurCost = node.CurCost CurValue = node.CurValue while True: # 判斷左結點能否加入到佇列,能的話,把當前空間和當前價值放入佇列 if CurCost + self.Cost[depth] < self.Volume: # 這時的父節點就是node self.enQueen(Node(CurCost + self.Cost[depth],CurValue + self.Value[depth],True,node),depth) # 右結點總是可以加入佇列的,因為沒有約束條件的限制 self.enQueen(Node(CurCost,CurValue,False,node),depth) # 然後彈出下一個結點 node = self.queue.pop(0) CurCost = node.CurCost CurValue = node.CurValue # 當同一層處理完畢時,先判斷是否能夠輸出結果,判斷的標準是佇列是否為空, # 這時下一層的所有結點已經加入了佇列,這時需要把下一層 # 增加一個結尾-1便於判斷,然後進入下一層,彈出下一個結點 if CurCost == -1: if not self.queue: return self.BestNode.CurValue self.enQueen(Node(-1,-1,False,None),depth) depth += 1 node = self.queue.pop(0) CurCost = node.CurCost CurValue = node.CurValue def solution_Tracking(self): #追蹤解從self.BestNode開始追蹤 for j in range(self.num-1,-1,-1): self.BestResult[j] = self.BestNode.isleft self.BestNode = self.BestNode.parent return self.BestResult def print_Result(self): print(self.pack_01()) print(self.solution_Tracking()) N = 8 V = 30 C = [11,2,3,9,13,6,15,7,19] W = [5.0,2.0,5.0,7.0,5.0,11.0,6.0,14.0] FIFO_01_Pack_with_solution_tracking(N,V,C,W).print_Result() 39.0 [False, True, True, True, False, True, False, True]