分支限界法实现(普通队列、优先队列、一般队列求解装载问题、优先队列求解装载问题)

**主要思想:**构造问题的解空间树,以广度优先(或进一步以最小耗费/最大效益优先)的方式搜索每个节点,通过约束条件和限界条件进行减枝,直至找到所需解或者结点搜索完成为止。
**广度优先:**队列
**最小耗费/最大效益优先:**最小堆/最大堆

普通队列

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