Java动态规划实现最短路径问题
问题描述
给定一个加权连通图(无向的或有向的),要求找出从每个定点到其他所有定点之间的最短路径以及最短路径的长度。
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动态规划实现最短路径问题的更多相关文章
- java动态规划取硬币问题
最近一直在研究动态规划的问题.今天遇到了取硬币问题. 其实动态规划还是,我从底部向顶部,依次求出每个状态的最小值,然后就可以标记上. 这道题目就是,假如有1,5,7,10这四种币值的硬币,我取14元, ...
- java动态规划问题
这里是简单的动态规划问题.其实,如果我们学过数据结构,应该就接触过动态规划问题,当时一直没有反应过来.我们求最小生成树用的是贪婪算法.而求最短路径就是动态规划.从一个点出发,到另外每个点的最短距离.在 ...
- Java动态规划
1. 介绍 动态规划典型的被用于优化递归算法,因为它们倾向于以指数的方式进行扩展.动态规划主要思想是将复杂问题(带有许多递归调用)分解为更小的子问题,然后将它们保存到内存中,这样我们就不必在每次使用它 ...
- java 动态规划解决最大连续子数列和
很多动态规划算法非常像数学中的递推.我们如果能找到一个合适的递推公式,就能很容易的解决问题.我们用dp[n]表示以第n个数结尾的最大连续子序列的和,这里第n个数必须在子序列中.于是存在以下递推公式: ...
- java动态规划导弹问题
这是一道动态规划题,和昨天的取硬币还有最长公共字串有点类似. 1.题目描述: 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一 ...
- 划分问题(Java 动态规划)
Description 给定一个正整数的集合A={a1,a2,-.,an},是否可以将其分割成两个子集合,使两个子集合的数加起来的和相等.例A = { 1, 3, 8, 4, 10} 可以分割:{1, ...
- 算法:矩阵连乘(Java)动态规划
Description 给你2个矩阵A.B,我们使用标准的矩阵相乘定义C=AB如下: A数组中栏(column)的数目一定要等于B数组中列(row)的数目才可以做此2数组的相乘.若我们以rows(A) ...
- java 动态规划解决上楼梯问题
问题描述: 你正在爬楼梯. 它需要n步才能达到顶峰. 每次你可以爬1或2步. 您可以通过多少不同的方式登顶? 注意:给定n将是一个正整数. Example 1: Input: 2 Output: 2 ...
- [leetcode] 45. 跳跃游戏 II(Java)(动态规划)
45. 跳跃游戏 II 动态规划 此题可以倒着想. 看示例: [2,3,1,1,4] 我们从后往前推,对于第4个数1,跳一次 对于第3个数1,显然只能跳到第4个数上,那么从第3个数开始跳到最后需要两次 ...
随机推荐
- 让写作省心一点——Markdown和CSS实践
1 引言 今天这篇推送和以往不太一样,乍一看就能发现格式有了变化.没错,这是我专门设计的品牌模板,也就是本公众号以后创作的文章可直接套用,获得一致的风格样式. 除此以外,文章里的全部元素(包括标题.表 ...
- 解决yum 问题
Dependencies Resolved Traceback (most recent call last): File "/usr/bin/yum", line 29, in ...
- 【雕爷学编程】MicroPython动手做(06)——零基础学MaixPy之单目摄像头
配套 OV2640摄像头:200W像素通用24P摄像头具有200万像素(1632x1232像素),其体积小.工作电压低,提供单片UXGA摄像和影像处理器的所有功能.通过SCCB总线控制,可以输出整帧. ...
- react-debug
最近练习react的时候遇到一些问题: 在redux模式下,同一个api依据参数获取不同data的时候,返回的data相同 原因:多次调用该接口时,action的type相同,导致对应于该接口的每个r ...
- Puppeteer笔记(一):Puppeteer简介
一.Puppeteer简介 Puppeteer是NPM库,它提供了NodeJS高级API来控制Chrome.Puppeteer 默认以无头(无界面)方式运行,但也可以配置为运行有界面的Chrome. ...
- JS 把数字转换成字母
JS 把数字转换成字母 2013-03-12 22:28:11 分类: JavaScript String.fromCharCode(addcount+65) 位运算alert(1<<0 ...
- 苏浪浪 201771010120 面向对象程序设计(Java)第13周
/实验十三 图形界面事件处理技术 1.实验目的与要求 (1) 掌握事件处理的基本原理,理解其用途: (2) 掌握AWT事件模型的工作机制: (3) 掌握事件处理的基本编程模型: (4) 了解GUI界 ...
- 微信小程序制作个人简历
使用微信小程序云开发制作自己的个人简历,简单高效. 首先需要了解小程序的基本结构以及云开发模式,及一些css样式基础. 使用小程序云数据库.vant组件库实现简历内容. 最终效果如下: 首先申请个人微 ...
- [JavaWeb基础] 029.OGNL表达式介绍
1.OGNL概述 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,它旨在提供一个更高的更抽象的层次来对 ...
- [Wireshark]_001_入门
Wireshark(前称Ethereal)是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进 ...