分支限界法實現(普通隊列、優先隊列、一般隊列求解裝載問題、優先隊列求解裝載問題)

**主要思想:**構造問題的解空間樹,以廣度優先(或進一步以最小耗費/最大效益優先)的方式搜索每個節點,通過約束條件和限界條件進行減枝,直至找到所需解或者結點搜索完成爲止。
**廣度優先:**隊列
**最小耗費/最大效益優先:**最小堆/最大堆

普通隊列

# 自定義結構體
# 創建隊列元素結構
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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章