**主要思想:**构造问题的解空间树,以广度优先(或进一步以最小耗费/最大效益优先)的方式搜索每个节点,通过约束条件和限界条件进行减枝,直至找到所需解或者结点搜索完成为止。
**广度优先:**队列
**最小耗费/最大效益优先:**最小堆/最大堆
普通队列
# 自定义结构体
# 创建队列元素结构
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()