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个数开始跳到最后需要两次 ...
随机推荐
- Mysql常用sql语句(21)- regexp 正则表达式查询
测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 正则的强大不言而喻,Mysql中也提供了 reg ...
- iview tree 绑定数据
官方文档 :https://www.iviewui.com/components/tree 效果图 1 主体分析 <Tree ref="tree" :data="t ...
- DevOps vs. Agile:它们有什么共同点?
DevOps与Agile有很多不同,但它们之间仍可发现很多共同点,这篇文章为读者揭晓. DevOps和Agile之间有着明显的关系.Agile是方法论,Scrum是框架,并DevOps随着看板也落在了 ...
- 宽字节XSS跨站攻击
简介 宽字节跨站漏洞多发生在GB系统编码. 对于GBK编码,字符是由两个字节构成,在%df遇到%5c时,由于%df的ascii大于128,所以会自动拼接%5c,吃掉反斜线.而%27 %20小于asci ...
- 前端:参数传错了,spring-boot:那错误信息我给你显示的友好点儿
之前两篇文章 Spring-boot自定义参数校验注解和如何在spring-boot中进行参数校验,我们介绍了,参数校验以及如何自定义参数校验注解,但是当传递参数出错时,只是把错误信息打印到了控制台, ...
- ReactNative报错:Can't find variable: __fbBatchedBridge
最近开始研究ReactNative,首先根据网上教程 http://www.codeceo.com/article/windows-react-native-android.html 一步一步来.完成 ...
- mysql5.7 derived_merge=on 影响你的查询了吗?
衍生表的优化:合并 | 具化 一.mysql优化器对于衍生表的优化处理可以从两方面进行: 将衍生表合并到外部查询 将衍生表具化为内部临时表 1.示例 1: SELECT * FROM (SELECT ...
- ScheduleMaster新特性之延时任务初体验
ScheduleMaster在上个月底更新到了2.0版本,在功能和代码以及文档上都往前跨了很大一步,详细信息可以参考这篇文章:https://www.cnblogs.com/hohoa/p/12772 ...
- Arthas 使用(二) —— 应用场景
1. ognl获取bean SpringContextUtil,通常代码中会有类似这样的工具类用来获取 bean 实例 @Component public class SpringContextUti ...
- jQuery中效果animate方法解决width是百分比出现的问题
jQuery中效果animate方法解决width是百分比出现的问题 http://www.mafutian.net/131.html 问题描述: 效果如图,初始化,每个层宽20%,采用animate ...