**主要思想:**構造問題的解空間樹,以廣度優先(或進一步以最小耗費/最大效益優先)的方式搜索每個節點,通過約束條件和限界條件進行減枝,直至找到所需解或者結點搜索完成爲止。
**廣度優先:**隊列
**最小耗費/最大效益優先:**最小堆/最大堆
普通隊列
# 自定義結構體
# 創建隊列元素結構
class QueueItem:
# i表示序號,w表示權重
def __init__(self, i, w):
self.i = i
self.w = w
# 打印當前隊列中元素
def printItem(queue):
for item in queue:
print(item.i, item.w)
# 進隊列
def EnQueue(queue, i, weight): # 使用自定義結構體入隊列
print('進隊列',i,weight)
tmp_item = QueueItem(i,weight)
queue.insert(0,tmp_item)
# 出隊列
def DeQueue(queue): # 出隊列
tmp_value = queue.pop()
print('出隊列',tmp_value.i,tmp_value.w)
if __name__ == '__main__':
# 1,2-2,5-3,6-4,9-5,7
queuelist = []
glist = input().split('-')
for i in glist:
itemstr = i.split(',')
EnQueue(queuelist, int(itemstr[0]), int(itemstr[1]))
print('當前隊列爲:')
printItem(queuelist)
print('')
while len(queuelist) != 0:
DeQueue(queuelist)
print('當前隊列爲:')
printItem(queuelist)
print('')
優先隊列(最大堆)
# 自定義結構體
# 創建隊列元素結構
class QueueItem:
# i表示序號,w表示權重
def __init__(self, i, w):
self.i = i
self.w = w
# 打印當前隊列中元素
def printItem(queue):
for item in queue:
print(item.i, item.w)
# 進優先隊列(最大堆)
def EnQueue(queue, i, wt): # 使用QueueItem數據結構
item = QueueItem(i, wt)
queue.append(item)
index = len(queue) - 1 #自底向上
while(index//2>0 and queue[index//2].w < queue[index].w):
tmp = queue[index // 2]
queue[index//2] = queue[index]
queue[index] = tmp
index = index//2
# 出優先隊列(最大堆)
def DeQueue(queue):
index = len(queue) - 1 #確定最後一個元素的索引
tmp = queue[1]
queue[1] = queue[index] #互換
queue[index] = tmp
maxitem = queue.pop() #出隊列
index = len(queue) - 1 #確定當前最後一個元素索引
i = 1 #自頂向下
while(i*2 <= index):
maxindex = i*2
if (2*i + 1 <= index): #如果有兩個子結點,求大的元素索引
if (queue[2*i+1].w>queue[2*i].w):
maxindex = 2*i+1
if queue[i].w < queue[maxindex].w: #如果父結點小,互換
tmp = queue[i]
queue[i] = queue[maxindex]
queue[maxindex] = tmp
i = maxindex
return maxitem
if __name__ == '__main__':
# 輸入
# 1,2-2,5-3,6-4,9-5,7
# 初始化優先隊列
queuelist = []
# 在優先隊列中放置一個索引爲0 不使用的元素,
# 保證後面堆插入刪除元素是從1開始,方便計算
item = QueueItem(-1, -1)
queuelist.append(item)
glist = input().split('-')
for i in glist:
itemstr = i.split(',')
EnQueue(queuelist, int(itemstr[0]), int(itemstr[1]))
print('當前隊列爲:')
printItem(queuelist)
print('')
while len(queuelist) != 1:
DeQueue(queuelist)
print('當前隊列爲:')
printItem(queuelist)
print('')
一般隊列求解裝載問題
# 分治限界法(一般隊列)實現裝載問題
import pdb
# 創建隊列元素
class QueueItem:
# 根據節點信息賦值
# i表示第幾層,cw表示當前載重,x解空間樹
def __init__(self, i, cw, x):
self.i = i
self.cw = cw
self.x = [i for i in x]
# 打印當前隊列中元素
def printItem(queue):
for item in queue:
print(item.i, item.cw, item.x)
# 判斷是進隊列還是更新當前最優值,記錄當前解x
def EnQueue(queue, x, wt, i, n): # 使用QueueItem數據結構
global bestw
if (i == n - 1):
# 葉子結點
if (wt >= bestw): # 這裏的'>='號很重要
bestw = wt
print("當前最優解:", str(x))
print("當前最優載重:", str(bestw))
else:
item = QueueItem(i, wt, x)
queue.insert(0, item)
# 從尾部出隊列
def DeQueue(queue): # 使用QueueItem數據結構
return queue.pop()
def BranchBound(): # 求裝載重量,限界右子樹,同時求裝載物品是哪些
global n # 物品個數
global x # 解空間樹表徵數組
global w # 物品重量數組
global c # 容量
global restw # 剩餘重量
global cw # 當前載重量
global bestw # 當前最優裝入重量
queuelist = [] # 隊列,從頭部插入,從尾部取出
item = QueueItem(-1,-1,x)
queuelist.insert(0, item)
i = 0 # 第一層
restw = restw - w[0] # 當前剩餘重量(即物品全部重量)減去第一個物品重量
while (True):
if item.i != -1:
x = item.x
cw = item.cw
sum_w = cw + w[i]
if sum_w <= c:
if bestw < sum_w:
bestw = sum_w
x[i] = 1
EnQueue(queuelist, x, sum_w, i, n)
if cw + restw >= bestw:
x[i] = 0
EnQueue(queuelist, x, cw, i, n)
item = DeQueue(queuelist)
if item.i == -1:
if len(queuelist) == 0:
print("最優裝載重量爲:", str(bestw))
return
else:
queuelist.insert(0,QueueItem(-1,-1,x))
item = DeQueue(queuelist)
i = i + 1
restw = restw - w[i]
if __name__ == '__main__':
# 3-3,2,2-4
# 3-2,2,3-4
# 5-3,2,2,1,1-6
glist = input().split('-')
# 物品個數
n = int(glist[0])
# 容量
c = int(glist[len(glist) - 1])
items = glist[1].split(',')
# 物品重量數組
w = [int(item) for item in items]
# 當前載重量
cw = 0
# 當前剩餘重量,初始等於全部物品重量
restw = 0
for i in w:
restw = restw + i
# 當前最優裝入重量
bestw = 0
# 解空間樹表徵數組
x = [0 for i in range(n)]
print('物品個數:', str(n))
print('物品重量數組:', str(w))
print('容量:', str(c))
BranchBound()
優先隊列求解裝載問題
# 分治限界法(優先隊列)實現裝載問題
import pdb
import copy
# 創建隊列元素
class QueueItem:
# 根據節點信息賦值
# i表示第幾層,cw表示當前載重,x解空間樹,para剩餘物品總重
def __init__(self, i, cw, x, para=0):
self.i = i
self.cw = cw
self.x = [i for i in x]
self.para = para
self.uweight = cw + para
# 按堆的方式插入結構元素
def InsertStructbyHeap(queue, item):
# 策略:先新節點先加到最後,然後從該節點向上調整不符合堆的元素位置
queue.append(item)
index = len(queue) - 1 # 自底向上
while (index // 2 > 0 and queue[index // 2].uweight < queue[index].uweight):
tmp = queue[index // 2]
queue[index // 2] = queue[index]
queue[index] = tmp
index = index // 2
# 按堆的方式刪除結構元素
def DeleteStructbyHeap(queue):
# 先將根節點與最後一個節點交換,刪除該元素後,從根元素開始調整不符合堆的元素位置
index = len(queue) - 1
queue[1], queue[index] = queue[index], queue[1]
maxitem = queue.pop()
index = len(queue) - 1
i = 1
while (i * 2 <= index):
maxindex = i * 2
if (2 * i + 1 <= index):
if (queue[2 * i + 1].uweight > queue[2 * i].uweight):
maxindex = 2 * i + 1
if queue[i].uweight < queue[maxindex].uweight:
queue[i], queue[maxindex] = queue[maxindex], queue[i]
i = maxindex
return maxitem
# 打印當前隊列中元素
def printItem(queue):
for item in queue:
print(item.i, item.cw, item.x, item.para, item.uweight)
# 優先參數定義爲:x.uweight=從根到結點x的當前載重量cw+剩餘集裝箱重量restw
def BranchBoundbyHeap(): # 求裝載重量,限界右子樹,加優先級,同時求裝載物品是哪些
global n # 物品個數
global x # 解空間樹表徵數組
global w # 物品重量數組
global c # 容量
global restw # 剩餘重量
global cw # 當前載重量
global bestw # 當前最優裝入重量
queuelist = [] # 優先隊列,第一個元素0默認,然後從1開始使用,取權值最大的出來
item = QueueItem(-1, -1, [])
queuelist.append(item) # 注意:這個元素只是佔據索引爲0的位置,並不使用,只是保證後面的堆從索引1開始
i = 0
while i != n:
restw = restw - w[i]
sum_w = cw + w[i]
if sum_w <= c:
if bestw < sum_w:
bestw = sum_w
x[i] = 1
item = QueueItem(i, sum_w, x, restw)
InsertStructbyHeap(queuelist, item)
if cw + restw >= bestw:
x[i] = 0
item = QueueItem(i, cw, x, restw)
InsertStructbyHeap(queuelist, item)
item = DeleteStructbyHeap(queuelist)
cw = item.cw
x = item.x
restw = item.para
i = item.i + 1
print("最優裝載重量爲:", str(cw))
print("最優解爲:", str(x))
if __name__ == '__main__':
# 3-3,2,2-4
# 3-2,2,3-4
# 5-3,2,2,1,1-6
glist = input().split('-')
# 物品個數
n = int(glist[0])
# 容量
c = int(glist[len(glist) - 1])
# 剩餘容量
rest = c
items = glist[1].split(',')
# 物品重量數組
w = [int(item) for item in items]
# 當前載重量
cw = 0
# 當前剩餘重量
restw = 0
for i in w:
restw = restw + i
# 揹包當前最優裝入重量
bestw = 0
# 解空間樹表徵數組
x = [0 for i in range(n)]
print('物品個數:', str(n))
print('物品重量數組:', str(w))
print('揹包容量:', str(c))
BranchBoundbyHeap()