一:思想
- 分支界限
- 首先要确定一个合理的限界函数(bound funciton),并根据限界函数确定目标函数的界[down ,up]
- 按照广度优先策略搜索问题的解空间树,在分直结点上依次扩展该结点的孩子结点,分别估算孩子结点的目标函数可能值,如果某孩子结点的目标函数可能超出目标函数的界,则将其丢弃;否则将其加入待处理结点表(简称PT表),依次从表PT中选取使目标函数取得极值的结点成为当前扩展结点,重复上述过程,直到得到最优解。
- 优先队列
- 按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。
- 本题的优先队列是:入队节点的最大的装载装载上界
二:程序的流程
- 分支界限
- 定义解空间(对解编码)
- 确定解空间的树结构
- 按BFS等方式搜索
- 每个活结点仅有一次机会变成扩展结点
- 由扩展结点生成一步可达的新结点
- 在新结点中,删除不可能导出最优解的结点 //限界策略
- 将剩余的新结点加入活结点表(队列)中
- 从活结点表中选择结点再扩展 //分支策略
- 直至活结点表为空
- 优先队列
- 按优先队列中规定的优先级,选取优先级最高的结点成为当前扩展结点。
- 每个结点都有一个对应的耗费或收益,以此决定结点的优先级。
- 如果查找一个具有最小耗费的解,则活结点可用小根堆来建立,下一个扩展结点就是具有最小耗费的活结点。
- 如果搜索一个具有最大收益的解,则可用大根堆来构造活结点表,下一个扩展结点是具有最大收益的活结点。
- 本题采用最大装载上限为条件的大根堆
三:流程图
四:算法解析
class Node:
def __init__(self, index, bestw, upbound):
"""
:param index: 表示第几个物品
:param upbound: 表明当前物品的装载上限
:param bestw: 表明最优装载量
"""
self.index = index
self.bestw = bestw
self.upbound = upbound
def __init__(self, ship_one, ship_two, num):
"""
:param bestw_list: 主要用来存储该阶段的策略
:param h: 存储大根堆
:param weight: 用来存储货物的总重量
:param ship_one, ship_two: 表示两艘船承受的总重量
:param num: 存储总和
:param count:表示入队顺序
"""
self.bestw = 0
self.num = num
self.h = []
self.weight = [0]
self.ship_one = ship_one
self.ship_two = ship_two
self.sum = 0
self.count = 0
- 主要的代码
- ①将头结点进行入队操作
- ②判断节点的bestw是否大于目前遇到节点的bestw,如果大于,就将结点bestw赋值给当前最大的bestw,否则不变
- ③将队列的头结点出队,然后判断该节点的下一个左右子树是否符合要求
- 右子节点的装载上限不能超过船的最大装载量
- 右子节点的最大装载上限需要大于最优装载量
- 左子节点的最大装载上限需要大于最优装载量
- 满足这样的条件的才能入队
- ④判断队列是否为空
- 采用的 主要是python的内置包heappush和heappop来进行活节点的存储和排序
def function(self):
node = Node(0, 0, self.sum)
heappush(self.h, (-node.upbound, self.count, node))
self.count += 1
while True:
if len(self.h) == 0:
break
node = (heappop(self.h))[2]
if node.bestw > self.bestw:
self.bestw = node.bestw
if node.index != self.num:
if node.bestw + self.weight[node.index + 1] <= self.ship_one and node.upbound >= self.bestw:
node_left = Node(node.index + 1, node.bestw + self.weight[node.index + 1], node.upbound)
heappush(self.h, (-node_left.upbound, self.count, node_left))
self.count += 1
if node.upbound - self.weight[node.index + 1] > self.bestw:
node_right = Node(node.index + 1, node.bestw, node.upbound - self.weight[node.index + 1])
heappush(self.h, (-node_right.upbound, self.count, node_right))
self.count += 1
五:完整代码
from heapq import heappush, heappop
class Node:
def __init__(self, index, bestw, upbound):
"""
:param index: 表示第几个物品
:param upbound: 表明当前物品的装载上限
:param bestw: 表明最优装载量
"""
self.index = index
self.bestw = bestw
self.upbound = upbound
class Loading:
def __init__(self, ship_one, ship_two, num):
"""
:param bestw_list: 主要用来存储该阶段的策略
:param h: 存储大根堆
:param weight: 用来存储货物的总重量
:param ship_one, ship_two: 表示两艘船承受的总重量
:param num: 存储总和
:param count:表示入队顺序
"""
self.bestw = 0
self.num = num
self.h = []
self.weight = [0]
self.ship_one = ship_one
self.ship_two = ship_two
self.sum = 0
self.count = 0
def function(self):
node = Node(0, 0, self.sum)
heappush(self.h, (-node.upbound, self.count, node))
self.count += 1
while True:
if len(self.h) == 0:
break
node = (heappop(self.h))[2]
if node.bestw > self.bestw:
self.bestw = node.bestw
if node.index != self.num:
if node.bestw + self.weight[node.index + 1] <= self.ship_one and node.upbound >= self.bestw:
node_left = Node(node.index + 1, node.bestw + self.weight[node.index + 1], node.upbound)
heappush(self.h, (-node_left.upbound, self.count, node_left))
self.count += 1
if node.upbound - self.weight[node.index + 1] > self.bestw:
node_right = Node(node.index + 1, node.bestw, node.upbound - self.weight[node.index + 1])
heappush(self.h, (-node_right.upbound, self.count, node_right))
self.count += 1
def input(self, num):
with open("weight.txt", "r") as f:
for i in range(num):
self.weight.append(int(f.readline()))
f.close()
for i in range(num + 1):
self.sum += self.weight[i]
def output(self):
if self.sum > self.ship_one + self.ship_two:
print("货物过多,装载不完")
print("第一艘船的装载货物重量为:".format(self.bestw))
if self.sum > self.bestw:
print("第二艘船装不完所有所有货物")
else:
print("第二艘船的装载重量为:".format(self.sum - self.bestw))
if __name__ == "__main__":
ship_one = int(input("请输入第一艘船的装载量:"))
ship_two = int(input("请输入第二艘船的装载量:"))
num = int(input("请输入货物的数量:"))
loading = Loading(ship_one=ship_one, ship_two=ship_two, num=num)
loading.input(num=num)
loading.function()
loading.output()
- 其中该目录下存储了一个txt文件夹
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191205212859372.png)