日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

限界分支法:01背包问题,优先级队列(包含解的追踪)

發布時間:2024/9/15 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 限界分支法:01背包问题,优先级队列(包含解的追踪) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前面提到:

不知道大家注意到沒有?上述實現方式沒有使用單位體積價值的排序,和之前提到01背包回溯法基于單位體積價值實現不一樣(先裝單位體積價值高的)。

我們網上經常看到都是基于以上實現的,到底這個用有什么好處了?實際上基于排序的單位體積價值是一個非常精確的限界函數

基于優先級隊列的實現方式,就需要用到以上的結構:

優先級隊列方式需要數據預處理,為什么需要預處理數據了,這里使用的是優先級隊列,這個優先級的選區非常重要,也非常重要
之前的策略curValue+rest就不行了,不是不行,是不夠好,那是一個粗糙的界,可以看到一開始選的就不是最優,然后又往回跳躍,因為在這種策略下,無法保證最優,這時需要精心挑選優先級,使之盡可能少往回跳躍或者跳低點,就像思考貪心策略那樣,實際上就是思考貪心策略,貪心就是配合優先級隊列使用的這里首先把數據安裝單位體積價值降序排列。

代碼實現如下:

import heapq class Nodes:def __init__(self,CurValue=None,CurCost=None,depth =None,parent=None,Flag=None):# 部分解所占體積self.CurCost = CurCost# 部分解所占價值self.CurValue = CurValue# 處于那一層self.depth = depth# 當前結點是否選擇了物品 self.isleft = Flag# 前一個結點是誰self.parent = parentclass PQ_pack_01_with_solution_tracking:def __init__(self,N,V,C,W):self.num = Nself.volume = Vself.cost = Cself.value = W#(0當前的價值,1,當前體積,2當前的深度,3父節點,4是否選擇了該物品)self.bestnode = Nodes(0,0,0,None,False)# 保存最后的方案self.bestsolution = [False]*N# 數據預處理,為什么需要預處理數據了,這里使用的是優先級隊列,這個優先級的選區非常重要,也非常重要# 之前的策略curValue+rest就不行了,因為在這種策略下,無法保證最優,這時需要精心挑選優先級,就像# 思考貪心策略那樣,實際上就是思考貪心策略,貪心就是配合優先級隊列使用的# 這里首先把數據安裝單位體積價值降序排列,self.order記錄與之前排列的標號,用于恢復最后結果self._cost,self._value,self.order = self.sort_group(N,C,W)# 把數據安裝單位體積價值降序排列def sort_group(self,N,C,W):# 原來數據的標號O = [i for i in range(N)]perp = [0]*Nfor i in range(N):perp[i] = W[i]/C[i]for i in range(N-1):for j in range(i+1,N):if perp[i] < perp[j]: temp = perp[i]perp[i] = perp[j]perp[j] = temptemp = O[i]O[i] = O[j]O[j] = temptemp = C[i]C[i] = C[j]C[j] = temptemp = W[i]W[i] = W[j]W[j] = temp return C,W,O# 限界函數,這個限界函數就非常精確,確保了每一次往下都是最優的策略def bound(self,depth,CurCost,CurValue):left_weight = self.volume - CurCostb = CurValuewhile depth < self.num and self._cost[depth] <= left_weight:left_weight -=self._cost[depth]b += self._value[depth]depth +=1if depth < N:b += (self._value[depth]/self._cost[depth]) * left_weightreturn bdef PQ_pack_01(self):pqueue = [] # 初始化,從root開始current_node = Nonecurrent_value = 0current_cost = 0depth = 0# 終止條件,優先級隊列里面存的是(0當前的價值,1,當前體積,2當前的深度,3父節點,4是否選擇了該物品)# 只要取第self.num層最優的current_value就可以了,只要到self.num層終止就行了while depth != self.num:# 滿足約束條件,存入左結點if current_cost + self._cost[depth] <= self.volume:# 每次進入左結點更新最優質,這樣方便剪枝,讓沒有必要的點不放進優先級隊列if current_value + self._value[depth] > self.bestnode.CurValue:self.bestnode.CurValue =current_value + self._value[depth]# 確定待放入結點的上界temp = self.bound(depth+1,current_cost+self._cost[depth],current_value+self._value[depth])# 把待放入結點的上界,當前價值,當前花費,當前層次,父親,是左是右放入優先級隊列# 因為是要求最大堆,隨意優先級取了-,heapq默認是取最小堆,直接求最大堆的包還不知道怎么用heapq.heappush(pqueue,(-temp,Nodes(current_value + self.value[depth],current_cost+self._cost[depth],depth+1,current_node,True)))# 對于右結點計算上界up = self.bound(depth+1,current_cost,current_value)# 加入上界小于當前最優質,就沒有必要放入優先級隊列,免得給優先級隊列增加負擔# 等于的情況需要放進去,因為這時路徑必須的,沒有等于0,就沒法深入了if up >= self.bestnode.CurValue:heapq.heappush(pqueue,(-up,Nodes(current_value,current_cost,depth+1,current_node,False)))# 彈出下一個最優的結點,0代表上界,1包含了所需要的信息current_node = heapq.heappop(pqueue)[1]current_value = current_node.CurValuecurrent_cost = current_node.CurCostdepth = current_node.depthprint(depth,current_value)self.bestnode = current_nodeprint(self.bestnode.CurValue)# 追蹤解 def solution_tracking(self):# 追蹤解,獲取最優方案BestResult =[False]*Nfor i in range(self.num -1,-1,-1):BestResult[i] = self.bestnode.isleftself.bestnode = self.bestnode.parent# 將最優方案翻譯成原來的排序 for i in range(N):if BestResult[i]:self.bestsolution[self.order[i]] = Trueprint(self.bestsolution)N = 8 V = 30 C = [11,2,3,9,13,6,15,7] W = [5.0,2.0,5.0,7.0,5.0,11.0,6.0,14.0]tt =PQ_pack_01_with_solution_tracking(N,V,C,W) tt.PQ_pack_01() tt.solution_tracking()1 14.0 2 25.0 3 30.0 4 32.0 5 39.0 6 39.0 7 39.0 4 30.0 8 39.0 39.0 [False, True, True, True, False, True, False, True]

總結

以上是生活随笔為你收集整理的限界分支法:01背包问题,优先级队列(包含解的追踪)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。