问题描述

给定一个加权连通图(无向的或有向的),要求找出从每个定点到其他所有定点之间的最短路径以及最短路径的长度。

2.1 动态规划法原理简介

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。

与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)

package com.liuzhen.floyd;

public class Floyd {

    //根据有向图的权重矩阵及起始的中间节点路径矩阵,返回最终图的距离矩阵及中间节点路径矩阵
public static void getShortestPath(int[][] chart,int[][] path){
int len = chart.length;
for(int k = 0;k < len;k++){ //k = 0表示,增加中间顶点a,k自增,表示后继增加第k个中间顶点(依次为b,c,d...)
for(int i = 0;i < len;i++){
for(int j = 0;j < len;j++){ int temp = 0; //新增一个中间顶点时,用该变量存储从i到k再到j的路径长度
if(chart[i][k] != 100 && chart[k][j] != 100) //当A[i][k]和A[k][j]路径都可以行走,100表示两顶点不相通
temp = chart[i][k] + chart[k][j]; if(chart[i][j] > temp && temp != 0) { //如果当前i到j路径长度(包括无法达到情况)大于以k为中间顶点的路径时
chart[i][j] = temp;
path[i][j] = k+1; //当两顶点相通,且是最短路径时,把k+1存入中间节点路径矩阵path中(PS:0表示i到j之间没有中间节点,1表示中间节点为a,所以此处为k+1,而不是用k,这样排除0的情况)
}
}
}
}
} //根据有向图的中间节点路径矩阵,以及两个顶点,返回这两个顶点之间的最短路径
public static String getOneShortestPath(int[][] path,int start,int end){
char startNode = (char) ('a' + start);
char endNode = (char) ('a' + end);
String nodePath = "";
if(path[start][end] == 0){
nodePath += startNode+"->"+endNode;
return nodePath;
}
int middle = path[start][end]-1;
//使用递归求解最短路径
nodePath += getOneShortestPath(path,start,middle)+" , "+getOneShortestPath(path,middle,end);
return nodePath;
} //输出有向图所有顶点之间的最短路径及最短路径长度
public static void printShortestPath(int[][] path,int[][] result){
int len = path.length;
for(int i = 0;i < len;i++){
char startNode = (char) ('a' + i);
for(int j = 0;j < len;j++){
char endNode = (char) ('a' + j);
String ijPath = startNode+"——>"+endNode+"最短路径为:";
String nodePath = getOneShortestPath(path,i,j);
System.out.println(ijPath+nodePath+" 。 路径长度为:"+result[i][j]);
}
}
} public static void main(String args[]){
/*chart数组中,数组0,1,2,3等表示两顶点之间的权重值,即两顶点间的距离大小, 100表示两顶点不相通*/
int[][] chart = {{0,100,3,100},{2,0,100,100},{100,7,0,1},{6,100,100,0}}; System.out.println("有向图chart的权重矩阵为(PS:其中值为100表示无穷大,即无法相通的路径):");
System.out.println("\t"+"a"+"\t"+"b"+"\t"+"c"+"\t"+"d");
for(int i = 0;i < 4;i++){
char startNode = (char) ('a' + i);
System.out.print(startNode+"\t");
for(int j = 0;j < 4;j++)
System.out.print(chart[i][j]+"\t");
System.out.println();
}
/*path数组中,0表示两顶点相通,1表示两顶点间有一个中间节点a,2表示 两顶点间有一个中间节点b,3两顶点间有一个中间节点c,4两顶点间有一个中间节点d.
* 100表示两顶点不相通*/
int[][] path = {{0,100,0,100},{0,0,100,100},{100,0,0,0},{0,100,100,0}};
getShortestPath(chart,path); System.out.println("有向图chart的距离矩阵为:");
System.out.println("\t"+"a"+"\t"+"b"+"\t"+"c"+"\t"+"d");
for(int i = 0;i < 4;i++){
char startNode = (char) ('a' + i);
System.out.print(startNode+"\t");
for(int j = 0;j < 4;j++)
System.out.print(chart[i][j]+"\t");
System.out.println();
} System.out.println("有向图chart的中间节点路径矩阵为(PS:值为0表示两节点直接相通,值为1表示两节点有一个中间节点a,值为2表示中间节点为b,依次类推):");
System.out.println("\t"+"a"+"\t"+"b"+"\t"+"c"+"\t"+"d");
for(int i = 0;i < 4;i++){
char startNode = (char) ('a' + i);
System.out.print(startNode+"\t");
for(int j = 0;j < 4;j++)
System.out.print(path[i][j]+"\t");
System.out.println();
} System.out.println("最终求取结果为:");
printShortestPath(path,chart); }
}
有向图chart的权重矩阵为(PS:其中值为100表示无穷大,即无法相通的路径):
a b c d
a 0 100 3 100
b 2 0 100 100
c 100 7 0 1
d 6 100 100 0
有向图chart的距离矩阵为:
a b c d
a 0 10 3 4
b 2 0 5 6
c 7 7 0 1
d 6 16 9 0
有向图chart的中间节点路径矩阵为(PS:值为0表示两节点直接相通,值为1表示两节点有一个中间节点a,值为2表示中间节点为b,依次类推):
a b c d
a 0 3 0 3
b 0 0 1 3
c 4 0 0 0
d 0 3 1 0
最终求取结果为:
a——>a最短路径为:a->a 。 路径长度为:0
a——>b最短路径为:a->c , c->b 。 路径长度为:10
a——>c最短路径为:a->c 。 路径长度为:3
a——>d最短路径为:a->c , c->d 。 路径长度为:4
b——>a最短路径为:b->a 。 路径长度为:2
b——>b最短路径为:b->b 。 路径长度为:0
b——>c最短路径为:b->a , a->c 。 路径长度为:5
b——>d最短路径为:b->a , a->c , c->d 。 路径长度为:6
c——>a最短路径为:c->d , d->a 。 路径长度为:7
c——>b最短路径为:c->b 。 路径长度为:7
c——>c最短路径为:c->c 。 路径长度为:0
c——>d最短路径为:c->d 。 路径长度为:1
d——>a最短路径为:d->a 。 路径长度为:6
d——>b最短路径为:d->a , a->c , c->b 。 路径长度为:16
d——>c最短路径为:d->a , a->c 。 路径长度为:9
d——>d最短路径为:d->d 。 路径长度为:0

Java动态规划实现最短路径问题的更多相关文章

  1. java动态规划取硬币问题

    最近一直在研究动态规划的问题.今天遇到了取硬币问题. 其实动态规划还是,我从底部向顶部,依次求出每个状态的最小值,然后就可以标记上. 这道题目就是,假如有1,5,7,10这四种币值的硬币,我取14元, ...

  2. java动态规划问题

    这里是简单的动态规划问题.其实,如果我们学过数据结构,应该就接触过动态规划问题,当时一直没有反应过来.我们求最小生成树用的是贪婪算法.而求最短路径就是动态规划.从一个点出发,到另外每个点的最短距离.在 ...

  3. Java动态规划

    1. 介绍 动态规划典型的被用于优化递归算法,因为它们倾向于以指数的方式进行扩展.动态规划主要思想是将复杂问题(带有许多递归调用)分解为更小的子问题,然后将它们保存到内存中,这样我们就不必在每次使用它 ...

  4. java 动态规划解决最大连续子数列和

    很多动态规划算法非常像数学中的递推.我们如果能找到一个合适的递推公式,就能很容易的解决问题.我们用dp[n]表示以第n个数结尾的最大连续子序列的和,这里第n个数必须在子序列中.于是存在以下递推公式: ...

  5. java动态规划导弹问题

    这是一道动态规划题,和昨天的取硬币还有最长公共字串有点类似. 1.题目描述:                        某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一 ...

  6. 划分问题(Java 动态规划)

    Description 给定一个正整数的集合A={a1,a2,-.,an},是否可以将其分割成两个子集合,使两个子集合的数加起来的和相等.例A = { 1, 3, 8, 4, 10} 可以分割:{1, ...

  7. 算法:矩阵连乘(Java)动态规划

    Description 给你2个矩阵A.B,我们使用标准的矩阵相乘定义C=AB如下: A数组中栏(column)的数目一定要等于B数组中列(row)的数目才可以做此2数组的相乘.若我们以rows(A) ...

  8. java 动态规划解决上楼梯问题

    问题描述: 你正在爬楼梯. 它需要n步才能达到顶峰. 每次你可以爬1或2步. 您可以通过多少不同的方式登顶? 注意:给定n将是一个正整数. Example 1: Input: 2 Output: 2 ...

  9. [leetcode] 45. 跳跃游戏 II(Java)(动态规划)

    45. 跳跃游戏 II 动态规划 此题可以倒着想. 看示例: [2,3,1,1,4] 我们从后往前推,对于第4个数1,跳一次 对于第3个数1,显然只能跳到第4个数上,那么从第3个数开始跳到最后需要两次 ...

随机推荐

  1. spring mvc --自定义converse

    在MVC中我们可以很轻松的根据项目需求进行必要的信息转换,如设置默认的日期格式,自定义String类型的格式等等... 配置中我们需要自定义converseService: <bean id=& ...

  2. python-修改文件

    1.修改文件1 # fw = open('username','w')# fw.write('hhhh')# fw.flush()  #强制把缓冲区里面的数据写到磁盘上1.简单粗暴直接#  1.打开一 ...

  3. 数据源管理 | OLAP查询引擎,ClickHouse集群化管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.列式库简介 ClickHouse是俄罗斯的Yandex公司于2016年开源的列式存储数据库(DBMS),主要用于OLAP在线分析处理查询, ...

  4. ql的python学习之路-day4

    集合(set) 集合主要有两种用处: 1.去除相同的元素 2.关系测试,两个列表中的元素的关系 按照‘alex’讲的自己写了源码笔记,下面就直接贴出来: #!/usr/bin/env python # ...

  5. 浅谈产品模型(Profile)在程序设计中的作用

    引言:物联网平台的一个重要功能就是资产管理,产品或者设备都可以看成是资产中组成部分,所以有时候说物联网平台可以进行产品管理和设备管理.通常应用物联网平台开发一套具有产品或者设备管理功能的系统的时候,必 ...

  6. Sentinel源码解析三(滑动窗口流量统计)

    前言 Sentinel的核心功能之一是流量统计,例如我们常用的指标QPS,当前线程数等.上一篇文章中我们已经大致提到了提供数据统计功能的Slot(StatisticSlot),StatisticSlo ...

  7. sound of the genuine

    “There is something in every one of you that waits and listens for the sound of the genuine in yours ...

  8. JSR303后端校验详细笔记

    目录 JSR303 使用步骤 关于不为空 分组校验 自定义校验 完整代码 JSR303 使用步骤 1.依赖 <!--数据校验--> <dependency> <group ...

  9. SpringBoot教程——检视阅读

    SpringBoot教程--检视阅读 参考 SpringBoot教程--一点--蓝本--springboot2.1.1 SpringBoot教程--易百--springboo2.0.5.RELEASE ...

  10. unity---string.Format()

    string.Format用法 string.Format("{0}{1}{2}",str1,str2,str3) string.Format("{0:D2}{1:D2} ...