单源最短路径问题——分支限界法(Java)

news2024/10/6 2:27:46

单源最短路径问题——分支限界法(Java)

文章目录

  • 单源最短路径问题——分支限界法(Java)
    • 1、 前置芝士
      • 1.1 分支限界法求解目标
      • 1.2 分支限界法引言
      • 1.3 分支限界法基本思想
      • 1.4 两种典型的解空间树
    • 2、分支限界法解题过程
      • 2.1 算法要点
      • 2.2 两个重要机制
      • 2.3 适用范围
      • 2.4 两种方式
    • 3、单源最短路径问题
      • 3.1 问题描述
      • 3.2 图解题目
    • 4、程序代码
    • 5、参考资料


在这里插入图片描述


1、 前置芝士

1.1 分支限界法求解目标

分支限界法与回溯法的不同求解目标:

  • 回溯法的求解目标:找出解空间树中满足约束条件的所有解

  • 分支限界法的求解目标:找出满足约束条件的一个解,或是在满足约束条件的解中找出使用某一目标函数值达到极大或极小的解,即在某种意义下的最优解

1.2 分支限界法引言

分支限界法与回溯法的不同搜索方式:

  • 回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。

  • 分支限界法的搜索策略:在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展对点。为了有效地选择下一扩展结点,以加速搜索的进程,在每一活结点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解

1.3 分支限界法基本思想

  • 分支限界法通常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。

  • 问题的解空间树是表示问题解空间的一棵有序树,常见的有子集树排列树

1.4 两种典型的解空间树

子集树(Subset Trees):

当所给问题是从n个元素的集合中找出满足某种性质的子集时,相应的解空间树称为子集树。在子集树中,|S0|=|S1|=…=|Sn-1|=c,即每个结点有相同数目的子树,通常情况下c=2,所以,子集树中共有2n个叶子结点,因此,遍历子集树需要O(2n)时间。

排列树(Permutation Trees):

当所给问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。在排列树中,通常情况下,|S0|=n,|S1|=n-1,…,|Sn-1|=1,所以,排列树中共有n!个叶子结点,因此,遍历排列树需要O(n!)时间。

2、分支限界法解题过程

2.1 算法要点

  • 在分支限界法中,每一个活结点只有一次机会成为扩展结点

  • 活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。

  • 从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程

  • 这个过程一直持续到找到所求的解或活结点表为空时为止。

活结点表:具有先进先出的性质,是队列

2.2 两个重要机制

  • 产生分支(解空间树)
  • 产生一个界限,能够终止许多分支(剪枝)

2.3 适用范围

  • 分支限界法类似于回溯法,有一些问题其实无论用回溯法还是分支限界法都可以得到很好的解决,但是另外一些则不然。

  • 下表列出了回溯法和分支限界法的一些区别:

在这里插入图片描述

2.4 两种方式

从活结点表中选择下一扩展结点的不同方式导致不同的分支限界法。

最常见的有以下两种方式:

  • 队列式(FIFO)分支限界法:队列式分支限界法将活结点表组织成一个队列,并按队列的先进先出原则选取下一个结点为当前扩展结点。

  • 优先队列式分支限界法:优先队列式分支限界法将活结点表组织成一个优先队列,按优先队列中规定的结点优先级选取优先级最高的下一个结点成为当前扩展结点。

常用堆来实现优先队列

3、单源最短路径问题

3.1 问题描述

给定带权有向图G =(V,E),其中每条边的权是非负实数.另外,还给定V中的一个顶点,称为源。现在要计算从源到所有其它各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题

在这里插入图片描述

优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树。其中,每一个结点内数字表示该结点所对应的当前路长

3.2 图解题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4、程序代码

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;


/**
 * TODO
 *   11 19
 *   SA 2 SB 3 SC 4 AF 7 AB 3 AE 2 BE 9 BD 2 CD 2 FG 9 FH 1 EH 3 ED 1 DI 1 DH 5 GT 7 HT 8 IH 2 IT 2
 */
public class t1 {
    static int N;   // 节点个数
    static int EDGES;   // 边的数量
    static float[][] adj;     // 邻接矩阵

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        System.out.print("input the number of vertix and edge:");
        N = scanner.nextInt();
        EDGES = scanner.nextInt();
        adj = new float[N + 1][N + 1];

        for (int i = 0; i < adj.length; i++) {
            for (int j = 0; j < adj.length; j++) {
                adj[i][j] = Float.MAX_VALUE;
            }
        }

        System.out.println("please input vertix and weight:");
        for (int i = 0; i < EDGES; i++) {
            String vertix = scanner.next();
            int startPos = vertix.charAt(0) - 'A' + 1, targetPos = vertix.charAt(1) - 'A' + 1;
            if (vertix.charAt(0) == 'S') {
                startPos = 0;
            }
            if (vertix.charAt(1) == 'T') {
                targetPos = N - 1;
            }
            float weight = scanner.nextFloat();
            adj[startPos][targetPos] = weight;
        }


        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (adj[i][j] != Float.MAX_VALUE && adj[i][j] != 0 && i != j) {
                    char start = (char) ('A' + i - 1), end = (char) ('A' + j - 1);
                    if (i == 0) {
                        start = 'S';
                    }
                    if (j == N - 1) {
                        end = 'T';
                    }
                    System.out.println("(" +  start + ", " + end  + ") = " + adj[i][j]);
//                    System.out.println("(" +  i + ", " + j  + ") = " + adj[i][j]);
                }
            }
        }

        int[] path = new int[N + 1];        // path[i]:记录最佳路径中,i的上一个顶点是path[i]
        float[] dist = new float[N + 1];    // dist[i]:从源点到当前顶点i的距离
        int vertix = 0;

        for (int j = 1; j <= N; j++) {
            dist[j] = Float.MAX_VALUE;
        }
        shortest(vertix, adj, dist, path);


        System.out.print("最小堆求解的路径为:");
//        for (int i = 1; i < path.length; i++) {
//            System.out.println(path[i]);
//        }
//        System.out.println("------------------------");

        // TODO 10 9 4 2 0
        List<Integer> list = new ArrayList<>();
        list.add(N - 1);
        list.add(path[N - 1]);
        while (true) {
            if (path[list.get(list.size() - 1)] == 0) {
                list.add(0);
                break;
            }
            list.add(path[list.get(list.size() - 1)]);
        }

//        for (int i = 0; i < list.size(); i++) {
//            System.out.println(list.get(i));
//        }
//        System.out.println("-------------------------");
        for (int j = list.size() - 1; j >= 0; j--) {
            if (list.get(j) == 0) {
                System.out.print("S-->");
            } else {
                char c = (char) (list.get(j) + 'A' - 1);
                if (j != 0) {
                    System.out.print(c + "-->");
                } else {
                    System.out.println('T');
                }
            }
        }


        System.out.println("从顶点S到各顶点最短距离:");
        for (int i = 1; i < dist.length - 1; i++) {
            char end = (char) ('A' + i - 1);
            System.out.print("dist[" + end + "] = " + dist[i] + " ");
        }
        System.out.println("dist[" + 'T' + "] = " +dist[10]);
    }

    public static void shortest(int v, float[][] adj, float[] dist, int[] path) {
        int n = path.length - 1;
        HeapNode enode = new HeapNode(v, 0);
        PriorityQueue<HeapNode> pq = new PriorityQueue<>();
        pq.offer(enode);

        while (!pq.isEmpty()) {
            HeapNode pollNode = pq.poll();
            int start = pollNode.vIdx;
            float currStep = pollNode.step;
            // 搜索问题的解空间
            for (int i = 1; i <= n; i++) {
                if (adj[start][i] <= Float.MAX_VALUE && pollNode.step + adj[start][i] < dist[i]) {
                    dist[i] = currStep + adj[start][i];
                    path[i] = start;
                    HeapNode node = new HeapNode(i, dist[i]);
                    pq.offer(node);
//                    System.out.println(start + "-->" + i);
                }
            }
        }
    }

    static class HeapNode implements Comparable {
        int vIdx;  // 顶点编号
        float step;   // 当前路长

        public HeapNode(int vIdx, float step) {
            this.vIdx = vIdx;
            this.step = step;
        }

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

其中,shorest方法的while()代码块可以用以下代码替换

while (true) {
        // 搜索问题的解空间
        for (int i = 1; i <= n; i++) {
            if (adj[enode.vIdx][i] < Float.MAX_VALUE && enode.step + adj[enode.vIdx][i] < dist[i]) {
                dist[i] = enode.step + adj[enode.vIdx][i];
                path[i] = enode.vIdx;
                HeapNode node = new HeapNode(i, dist[i]);
                pq.offer(node);
            }
        }
        if (pq.isEmpty()) {
            break;
        } else {
            // 移除
            enode = (HeapNode) pq.poll();
        }
    }

运行结果

在这里插入图片描述

5、参考资料

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

结束!

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

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

相关文章

java 实现对数据表的备份与还原(备份与还原 到服务器中)

java备份还原表数据 背景 需求&#xff1a;这个功能还是费了我一段时间才完成&#xff0c;大体的需求是这样的。 首先是 分模块&#xff0c;每个模块有不同的几个表&#xff0c;备份的时候就按照模块来备份数据&#xff0c;相当于一次性备份多张表的数据了&#xff0c;模块 和…

攻防世界-baigeiRSA

1.下载附件&#xff0c;得到压缩包&#xff0c;解压得到两个文件。 import libnum from Crypto.Util import number from secret import flagsize 128 e 65537 p number.getPrime(size) q number.getPrime(size) n p*qm libnum.s2n(flag) c pow(m, e, n)print(n %d % …

(已更新)Discuz手机模板:NVBING5-APP手机版,界面美观大方,可封装安卓/苹果APP,模板文件+插件+分类信息导入文件

Discuz手机模板&#xff1a;NVBING5-APP手机版——是一款界面美观大方的完整Discuz手机模板&#xff0c;附带模板插件分类信息导入文件详细的安装说明模块说明。 功能介绍 *支持封装安卓APP、苹果APP&#xff0c;原生微信登录、分享等几十项功能 *支持视频上传至优酷云或本地…

水溶性荧光团磺酸基-花青素Cy7 酪酰胺,Tyramide-Sulfo-Cy7

磺酸基-花青素Cy7 酪酰胺是一种水溶性荧光团&#xff0c;用于近红外光谱部分。由于其结构中存在三亚甲基桥&#xff0c;使其量子产率比其他七甲基菁高。氟化染料是理想的体内成像应用。一个非氟化版本&#xff0c;Cyanine7&#xff0c;也可用。 『英文名称』&#xff1a;Tyram…

基础SQL语法语句大全(一篇学会所有SQL语句)

如&#xff1a;select distinct name from student; 如&#xff1a;select name,salary from employee where deptno 3; 如&#xff1a;select * from employees where deptno 3 and salary>-5000;(两个条件同时满足) select * from employees where (deptno 3 or depton…

HARDiNFO Pro 8.0 绿色版-轻便版

HARDiNFO 一体化系统信息、诊断和基准测试 主要特点 硬件清单、计算机管理、基准测试和网络监控 硬件库存 获取有关您的 PC 硬件组件和外围设备的详细系统信息&#xff0c;例如&#xff1b;CPU、内存、主板、显示适配器、HDD/SSD 磁盘驱动器、显示器、笔记本电池、操作系统驱动…

[附源码]JAVA毕业设计医院门诊挂号系统(系统+LW)

[附源码]JAVA毕业设计医院门诊挂号系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

【QT 5 学习笔记-学习绘图相关+画线图形等+绘图事件+基础学习(1)】

【QT 5 学习笔记-学习绘图相关画线图形等绘图事件基础学习&#xff08;1&#xff09;】1、说明2、实验环境3、参照学习链接4、自己的学习与理解5、学习与实践代码。&#xff08;1&#xff09;建立基础工程。&#xff08;2&#xff09;加入绘图事件与包含库&#xff08;3&#x…

自然语言处理(NLP)数据集汇总 2(附下载链接)

&#x1f384;&#x1f384;【自然语言处理NLP】简介 &#x1f384;&#x1f384; 自然语言处理(Natural Language Processing, NLP)是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门…

真是绝了!git标星9K

能力f&#xff08;认知&#xff0c;洞察&#xff0c;实践&#xff0c;经验总结&#xff09; 不知道你到了哪个阶段了呢&#xff1f; 架构是软件工程的实践艺术&#xff0c;要化理想为现实&#xff0c;不是空中楼阁。懂得再多的设计理念、方法论&#xff0c;光说不练还是假把式…

大二学生《Web编程基础》期末网页制作 HTML+CSS个人网页设计实例

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

8年前端带你HTML+CSS入门到实战(附视频+源码)

本文主要是解决&#xff1a; ☆ 想要自学前端开发&#xff0c; ☆ 但又不太想看博客文章&#xff0c; ☆ 觉得自学有点吃力&#xff0c;有点不知道学习步骤的同学 目录 一、HTML 1、需要了解熟练的标签 2、不太常用的标签 3、怎么算是HTML学好了&#xff0c;可以继续学CSS了…

ChatGPT教你面试阿里P6测试开发岗

​持续坚持原创输出&#xff0c;点击蓝字关注我吧 最近ChatGPT爆火&#xff0c;ChatGPT能干什么呢&#xff1f;想必已经看过很多文章了&#xff0c;例如ChatGPT通过美国高考、ChatGPT开发游戏、调试代码、写文章等等。 哈哈&#xff0c;作为一个软件测试博主&#xff0c;我怎么…

Java和MySQL的连接和操作(JDBC)

一、数据库的连接 1. 引入JDBC驱动程序 1.1 如何获取驱动程序 驱动程序由数据库提供商提供下载。 MySQL 的驱动下载地址&#xff1a;http://dev.mysql.com/downloads/ 依次点击 Connector/J -> Platform Independent &#xff0c;如然后下载下面那个 1.2 如何在Java …

ADI Blackfin DSP处理器-BF533的开发详解25:LCD_ZIKU(字库在液晶屏上的应用)(含源代码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 代码实现了将字库信息显示到液晶屏上。 代码使用说明 增加了液晶屏驱动&#xff0c;将内存数据显示到液晶屏上。 内存数据转换&…

[附源码]Python计算机毕业设计大学生兼职推荐系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Git从入门到实战

Git从入门到实战 一、Git概述 1.1、Git简介 Git是一个分布式版本控制工具&#xff0c;通常用来对软件开发过程中的源代码文件进行管理。Git仓库来存储和管理这些文件&#xff0c;Git仓库分为两种&#xff1a; 本地仓库&#xff1a;开发人员自己电脑上的Git仓库远程仓库&…

微服务框架 SpringCloud微服务架构 微服务保护 32 隔离和降级 32.1 Feign整合Sentinel

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务保护 文章目录微服务框架微服务保护32 隔离和降级32.1 Feign整合Sentinel32.1.1 隔离和降级32.1.2 Feign 整合Sentinel32.1.3 总结32 …

算法设计与分析期末复习(一)

算法的定义和特征 什么是算法&#xff1f; 算法是求解某一特定问题的一组有穷规则的集合&#xff0c;它是由若干条指令组成的有穷符号串。算法的五个重要特性 确定性&#xff1a;算法中每一条指令必须有确切的含义&#xff0c;不存在二义性。只有一个入口和一个出口。 可行性&…

raft协议详解

文章目录1. 分布式系统数据一致性概述2. rafts算法基础2.1 基础2.2leader选举2.3raft算法数据同步2.4 raft算法之脑裂2.5 leader宕机处理raft 动画演示1. 分布式系统数据一致性概述 redis保证了可用性&#xff0c;牺牲了一致性 2. rafts算法基础 2.1 基础 2.2leader选举 2.3r…