装载问题 ——分支限界法(Java)

news2024/12/22 18:56:15

装载问题 ——分支限界法(Java)

文章目录

  • 装载问题 ——分支限界法(Java)
    • 1、 问题描述
    • 2、算法设计
    • 3、算法的改进
    • 4、程序代码
    • 5、参考资料


在这里插入图片描述


1、 问题描述

有一批共n个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集
装箱i的重量为Wi,且

∑ i = 1 n w i < = C 1 + C 2 \sum_{i=1}^{n} w_i <= C1 + C2 i=1nwi<=C1+C2

装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船。如果有,找出一种装载方案。

容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。

  • 首先将第一艘轮船尽可能装满;

  • 将剩余的集装箱装上第二艘轮船。

2、算法设计

队列式分支限界法

在算法的while循环中,首先检测当前扩展结点的左儿子结点是否为可行结点。如果是则将其加入到活结点队列中。然后将其右儿子结点加入到活结点队列中(右儿子结点一定是可行结点)。2个儿子结点都产生后,当前扩展结点被舍弃。

活结点队列中的队首元素被取出作为当前扩展结点,由于队列中每一层结点之后都有一个尾部标记-1,故在取队首元素时,活结点队列一定不空。当取出的元素是-1时,再判断当前队列是否为空。如果队列非空,则将尾部标记-1加入活结点队列,算法开始处理下一层的活结点。

核心代码

while (true)
      {                                                                                  
         if (ew + w[i] <= c)        enQueue(ew + w[i], i);      // 检查左儿子结点
         enQueue(ew, i);                                                       //右儿子结点总是可行的
         ew = ((Integer) queue.remove()).intValue();          // 取下一扩展结点
         if (ew == -1)
         {   if (queue.isEmpty())    return bestw;
             queue.put(new Integer(-1));                                // 同层结点尾部标志
             ew = ((Integer) queue.remove()).intValue();      // 取下一扩展结点
             i++;                                                                      // 进入下一层         }    
  }

在这里插入图片描述

3、算法的改进

  • 节点的左子树表示将此集装箱装上船,右子树表示不将此集装箱装上船。设bestw是当前最优解;ew是当前扩展结点所相应的重量;r是剩余集装箱的重量。则当ew+r<=bestw时,可将其右子树剪去,因为此时若要船装最多集装箱,就应该把此箱装上船。

  • 另外,为了确保右子树成功剪枝,应该在算法每一次进入左子树的时候更新bestw的值。

构造最优解

为了在算法结束后能方便地构造出与最优值相应的最优解,算法必须存储相应子集树中从活结点到根结点的路径。为此目的,可在每个结点处设置指向其父结点的指针,并设置左、右儿子标志。

在这里插入图片描述

在这里插入图片描述

FIFO+限界搜索过程:

在这里插入图片描述

1) 初始队列中只有结点A;

2) 结点A变为E-结点扩充B入队,bestw=10;结点C的装载上界为30+50=80>bestw,也入队;

3) 结点B变为E-结点扩充D入队,bestw=40;结点E的装载上界为60>bestw,也入队;

4) 结点C变为E-结点扩充F入队,bestw仍为40;结点G的装载上界为50>bestw,也入队;

5) 结点D变为E-结点,叶结点H超过容量,不入队;叶结点I的装载上界为40=bestw=40,不入队

6) 结点E变为E-结点,叶结点J装载上界为60>bestw=40, 入队,并将bestw更新为60;叶结点K的装载上界为10<bestw=40,不入队,即被剪掉;

7) 结点F变为E-结点,叶结点L超过容量,不入队,bestw仍为60;叶结点M的装载上界为30<bestw=60,被剪掉;

8) 结点G变为E-结点,叶结点N、O都被剪掉;

9)结点J变为E-结点, 由于J是叶子结点,算法结束。

优先队列式分支限界法

解装载问题的优先队列式分支限界法用最大优先队列存储活结点表。活结点x在优先队列中的优先级定义为从根结点到结点x的路径所相应的载重量再加上剩余集装箱的重量之和

优先队列中优先级最大的活结点成为下一个扩展结点。以结点x为根的子树中所有结点相应的路径的载重量不超过它的优先级。子集树中叶结点所相应的载重量与其优先级相同。

在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。此时可终止算法。

在这里插入图片描述

分支限界(LC)-搜索的过程如下:优先队列分枝限界搜索

1) 初始队列中只有结点A;

2) 结点A变为E-结点扩充B入堆,bestw=10;结点C的装载上界为30+50=80>bestw,也入堆;堆中B上界为90,在优先队列之首;

3) 结点B变为E-结点扩充D入堆,bestw=40;结点E的装载上界为60>bestw,也入堆;此时堆中D上界为90,在优先队列之首;

4) 结点D变为E-结点,叶结点H超过容量,叶结点I的装载上界为40>=bestw=40,入堆;此时堆中C上界为80,在优先队列之首。

5) 结点C变为E-结点扩充F入堆,bestw仍为40; 结点G的装载上界为50>bestw,也入堆;此时堆中E上界为60,在优先队列之首。

6) 结点E变为E-结点,叶结点J装载量为60,入堆,bestw变为60; 叶结点K上界为10< bestw,被剪掉;此时堆中J上界为60,在优先队列之首。

7)结点J变为E-结点(叶子结点),扩展的层次为4(或队首结点为叶子),算法结束。

虽然此时堆并不空,但可以确定已找到了最优解。

4、程序代码

import java.util.PriorityQueue;

public class Solution {
    // 类数据成员
    static int N;                   // 集装箱数量 - 1
    static int[] best;              // 当前最优解,best[i]表示第i+1个集装箱装载到第best[i]+1艘轮船时最优
    static int[] weight;
    static int[] shipContain;
    static int extendWeight;
    static PriorityQueue<HeapNode> heap;  // 活结点队列
    static int[] remainArr;

    public static void main(String[] args) {
        weight = new int[]{20, 24, 15, 25};     // 每个集装箱重量(从下标1开始)
//        weight = new int[]{10, 20, 36, 25};     // 每个集装箱重量(从下标1开始)
//        weight = new int[]{30, 30, 30, 50, 50, 60};     // 每个集装箱重量
//        shipContain = new int[]{100, 150};             // 两艘轮船的载重量分别为C1,C2

        N = weight.length - 1;
        heap = new PriorityQueue<HeapNode>((a, b) -> b.uweight - a.uweight);
        best = new int[N + 1];
        // 定义剩余重量数组
        remainArr = new int[N + 1];
        for (int i = N - 1; i >= 0; i--) {
            remainArr[i] = remainArr[i + 1] + weight[i + 1];
        }

        System.out.print("集装箱重量分别为:");
        for (int i = 0; i < weight.length; i++) {
            if (i != weight.length - 1) {
                System.out.print(weight[i] + " ");
            } else {
                System.out.println(weight[i]);
            }
        }
        int c1 = 54;
        System.out.println("轮船1最大载重量为" + c1);

        // TODO best[i] = 1 表示装载 0表示为未装载
        System.out.println("轮船1的最优载重量为:" + maxLoading1(weight, c1, best));;
//        System.out.println("集装箱1的最优载重量为:" + maxLoading1(weight, shipContain[0], best));;
//        System.out.println("集装箱2的最优载重量为:" + maxLoading1(weight, shipContain[1], best));;
//        System.out.println(maxLoading1(weight, shipContain[0], best));;
    }

    // TODO 队列式分支限界法
    public static int maxLoading1(int[] w, int c, int[] best) {
        BBnode e = null;        // 当前扩展节点
        int currLevel = 0;          // 当前扩展节点所处的层序号
        int extendWeight = 0;         // 扩展节点所对应的载重量

        // 搜索子集空间树
        while (currLevel != N + 1) {
            // TODO 检查当前扩展结点的左儿子结点
            int wt = extendWeight + w[currLevel];
            if (wt <= c) {
                // 左儿子结点为可行节点
                addLiveNode(wt + remainArr[currLevel], currLevel + 1, e, true);
            }
            // TODO 检查右儿子结点
            addLiveNode(extendWeight + remainArr[currLevel], currLevel + 1, e, false);

            // 取下一扩展结点
            HeapNode node = heap.poll();
            currLevel = node.level;
            e = node.liveNode;
            extendWeight = node.uweight - remainArr[currLevel - 1];
        }
        // 构造当前最优解
        System.out.println("最优解数组为:");
        for (int i = 0; i <= N; i++) {
            best[i] = (e.leftChild) ? 0 : 1;
            if (i != N) {
                System.out.print(best[i] + " ");
            } else {
                System.out.println(best[i]);
            }
            e = e.parent;
        }
        return extendWeight;
    }

    /**
     * TODO 将活结点加入到表示活结点优先队列的最大堆中
     * @param up
     * @param lev
     * @param par
     * @param lChild
     */
    public static void addLiveNode(int up, int lev, BBnode par, boolean lChild) {
        BBnode b = new BBnode(par, lChild);
        HeapNode node = new HeapNode(b, up, lev);
        heap.add(node);
    }

    static class HeapNode implements Comparable {
        BBnode liveNode;        // 活结点
        int uweight;            // 活结点优先级
        int level;              //活结点在子集树种所处的层序号

        public HeapNode(BBnode node, int up, int lev) {
            liveNode = node;
            uweight = up;
            level = lev;
        }

        @Override
        public int compareTo(Object o) {
            int oUW = ((HeapNode) o).uweight;
            if (uweight < oUW) {
                return -1;
            }
            if (uweight == oUW) {
                return 0;
            }
            return 1;
        }

        @Override
        public boolean equals(Object obj) {
            return uweight == ((HeapNode) obj).uweight;
        }
    }

    static class BBnode {
        BBnode parent;
        boolean leftChild;

        public BBnode(BBnode par, boolean lchild) {
            parent = par;
            leftChild = lchild;
        }
    }
    
}

运行结果

在这里插入图片描述

5、参考资料

  • 算法设计与分析(第四版)

结束!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/87423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数图互通高校房产管理——教职工住宅方案

数图互通房产管理系统在这方面做得比较全面&#xff1b; 1、住房管理 1.1 住房档案 住房模块的管理主要是针对学校的承租住宅和已售住宅的管理&#xff0c;用于登记已售住宅的产权人信息&#xff0c;记录承租住宅的租赁起止日期、月租金等基本信息。 支持住房的坐落信息、楼栋…

Cas:146368-11-8(水溶)|Sulfo CY5-羧酸|Cyanine5 Carboxylic Acidic acid

Cas:146368-11-8(水溶)|Sulfo CY5-羧酸|Cyanine5 Carboxylic Acidic acid Sulfo CY5-羧酸这种分子可以被认为是非活性染料&#xff0c;用于控制样品和仪器校准。为了与胺和蛋白质标记偶联&#xff0c; 中文名&#xff1a;Sulfo CY5-羧酸 英文名&#xff1a;Cyanine5 Carboxy…

rate-limit 一款 java 开源渐进式分布式限流框架使用介绍

项目简介 rate-limit 是一个为 java 设计的渐进式限流工具。 目的是为了深入学习和使用限流&#xff0c;后续将会持续迭代。 特性 渐进式实现 支持独立于 spring 使用 支持整合 spring 支持整合 spring-boot 内置多种限流策略 快速开始 需求 jdk 1.7 maven 3.x mav…

ARM S5PV210 时钟系统与时钟体系框图

前言 This chapter describes the clock management unit (CMU) supported by S5PV210. The system controller (SYSCON) manages CMU and power management unit (PMU) in S5PV210. 本章介绍 S5PV210 支持的时钟管理单元&#xff08;CMU&#xff09;。系统控制器&#xff08…

【软考】系统集成项目管理工程师(十一)项目人力资源管理

一、项目人力资源管理概述二、激励理论1. 马斯洛需求层次理论2. 赫茨伯格的双因素理论3. X 理论/ Y 理论4. 期望理论三、人力资源管理子过程1. 规划人力资源管理2. 组建项目团队3. 建设项目团队4. 管理项目团队一、项目人力资源管理概述 在了解人力资源管理之前,我们先来认识…

从局部到全局:语义相似度的测地线距离

©PaperWeekly 原创 作者 | 苏剑林单位 | 追一科技研究方向 | NLP、神经网络前段时间在最近的一篇论文《Unsupervised Opinion Summarization Using Approximate Geodesics》[1] 中学到了一个新的概念&#xff0c;叫做“测地线距离&#xff08;Geodesic Distance&#xff…

.net开发安卓入门 - Service (服务)

.net开发安卓入门 - Service Android Service 概述Service VS Thread &#xff08;服务和线程之间进行选择&#xff09;前台服务代码启动前台服务方法运行效果后台服务代码启动代码绑定服务AIDL同系列文章推荐Android Service 概述 移动应用不像桌面应用。 桌面具有大量资源&a…

基于51单片机的正弦波发生器设计

程序运行图&#xff1a; 仿真原理图&#xff1a; 部分程序&#xff1a; #include <reg52.h> //接口定义 sbit DA P1^1; sbit CK P1^2; sbit CS P1^4; //10bit取样&#xff0c;1024点正弦查表数据 unsigned int code sine_dot[1024] { 0x200,0x203,0x206,0x209,…

可视化编排的数据集成和分发开源框架Nifi轻松入门-上

文章目录概述定义dataflow面临挑战特性核心概念架构高级概述安装部署常见处理器入门示例概述 定义 Nifi 官网地址 https://nifi.apache.org/ Nifi 官网文档 https://nifi.apache.org/docs.html Nifi GitHub源码地址 https://github.com/apache/nifi Apache NiFi是一个易于使用…

NetInside助力IT提高业务性能管理能力(二)

​​需求简介 某外高桥公司的OA系统是其重要的业务系统&#xff0c;OA系统负责人表示&#xff0c;部分用户反馈&#xff0c;访问OA系统时比较慢。需要通过分析系统看一下实际情况。 本次分析重点针对OA系统性能进行分析&#xff0c;以供安全取证、性能分析、网络质量监测以及…

关于推特隐私设置的一些小窍门

大家在使用推特进行引流的时候&#xff0c;在使用的时候难免会遇到一些功能模糊不清&#xff0c;这里twitter群推王给大家总结了一些偏门功能应该如何去设置&#xff0c;让你使用起来更加得心应手。 一、推特怎么设置自动放声音 1、首先打开推特APP并登陆。 2、其次在推特主…

CPDA认证|数据分析能给企业带来哪些好处?

数据分析的核心并不在于数据本身&#xff0c;而在于设计有意义、有价值的数据分析主题与指标体系&#xff0c;通过科学有效的手段去分析&#xff0c;进而发现问题优化迭代。 无论分析给出的结果是积极的还是负面的&#xff0c;都是价值承载体&#xff0c;必须以客观的态度面对。…

Enum枚举

枚举一般是针对常量需求,优化代码,.使代码看起来简洁 看下下面这个工具类 说有问题,那就是是看起来代码不够简洁 我看着倒还行,也许也是枚举不怎么实用的原因 下面就用枚举来优化这个代码,首先看下枚举介绍 java中对常量数据的配置可以使用枚举类型实现,,枚举类型是面向对象…

3小时!开发ChatGPT微信小程序

导读 | 上周OpenAI发布了对话语言模型 ChatGPT&#xff0c;相关讨论引爆全网。你是否也迫不及待体验一番&#xff1f;本文特邀作者腾讯云开发者社区作者戴传友从开发环境准备、开发过程、服务器接口、腾讯API网关接入到部署&#xff0c;详细教你如何动手开发一个chatGPT微信小程…

2022年华中杯数学建模挑战赛A题分拣系统优化问题

2022年华中杯数学建模 A 题 分拣系统优化问题 真的有想占便宜的 醉了 几十元让我写论文这是什么选手 想占便宜想疯了么 还要求查重率在10% 一开始说想看看你的A题论文 想学习一下 然后谈完价(几十块钱)之后 需要改成现做一篇独一无二的论文 然后想套路我占便宜 套路是真的深啊…

【R语言绘图】R在气象、水文中数据处理及结果分析、绘图技术

【查看原文】R语言在气象、水文中数据处理及结果分析、绘图实践技术应用 【内容简述】&#xff1a; 一、R简介与 R 在气象水文中的应用 R语言与 R软件简介 R 在各行业的应用 R 与其他语言的比较及其在数据分析与作图上的优势 R 在地学中的应用以及R 在气象水文中的应用 二、…

【react】虚拟DOM的两种创建方式

1、使用js创建虚拟DOM <body><div id"test"></div><!-- 引入react核心库 --><script src"../js/react.development.js"></script><!-- 引入react-dom&#xff0c;用于支持react操作dom --><script src"…

大数据期末课设~基于spark的气象数据处理与分析

目录 一 、项目背景 .......................................... 3 二 、实验环境 .......................................... 3 三 、实验数据来源 ................................... 4 四 、数据获取 .......................................... 5 五 、数据分析 ....…

港科夜闻|2022年香港科大气候适应及复原力大会圆满闭幕,政经领袖研讨香港气候政策与绿色金融发展...

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、2022年香港科大气候适应及复原力大会圆满闭幕&#xff0c;政经领袖研讨香港气候政策与绿色金融发展。该会议由香港科大主办&#xff0c;于12月10日开幕。会议以跨领域的知识及观点交流为方针&#xff0c;凝聚公营及私营部门…

vulnhub serial讲解

环境搭建 下载 https://download.vulnhub.com/serial/serial.zip ​ 你会得到一个这样的文件&#xff0c;这里使用VMware新建一个虚拟机&#xff0c;这里记录比较重要的几部分。 ​ ​ ​ ​ 这里就是使用我们刚才下过来的。 ​ 漏洞过程详解 1.信息收集 netdiscover -i …