算法详解(五):分支界限-装载问题

一:思想

  • 分支界限
    • 首先要确定一个合理的限界函数(bound funciton),并根据限界函数确定目标函数的界[down ,up]
    • 按照广度优先策略搜索问题的解空间树,在分直结点上依次扩展该结点的孩子结点,分别估算孩子结点的目标函数可能值,如果某孩子结点的目标函数可能超出目标函数的界,则将其丢弃;否则将其加入待处理结点表(简称PT表),依次从表PT中选取使目标函数取得极值的结点成为当前扩展结点,重复上述过程,直到得到最优解。
  • 优先队列
    • 按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。
    • 本题的优先队列是:入队节点的最大的装载装载上界

二:程序的流程

  • 分支界限
    • 定义解空间(对解编码)
    • 确定解空间的树结构
    • 按BFS等方式搜索
      • 每个活结点仅有一次机会变成扩展结点
      • 由扩展结点生成一步可达的新结点
      • 在新结点中,删除不可能导出最优解的结点 //限界策略
      • 将剩余的新结点加入活结点表(队列)中
      • 从活结点表中选择结点再扩展 //分支策略
      • 直至活结点表为空
  • 优先队列
    • 按优先队列中规定的优先级,选取优先级最高的结点成为当前扩展结点。
    • 每个结点都有一个对应的耗费或收益,以此决定结点的优先级。
      • 如果查找一个具有最小耗费的解,则活结点可用小根堆来建立,下一个扩展结点就是具有最小耗费的活结点。
      • 如果搜索一个具有最大收益的解,则可用大根堆来构造活结点表,下一个扩展结点是具有最大收益的活结点。
      • 本题采用最大装载上限为条件的大根堆

三:流程图

四:算法解析

  • 活节点:采用python类的思想来存储活节点
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文件夹在这里插入图片描述
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值