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个数开始跳到最后需要两次 ...
随机推荐
- 在微服务框架Demo.MicroServer中添加SkyWalking+SkyApm-dotnet分布式链路追踪系统
1.APM工具的选取 Apm监测工具很多,这里选用网上比较火的一款Skywalking. Skywalking是一个应用性能监控(APM)系统,Skywalking分为服务端Oap.管理界面UI.以及 ...
- Mysql 常用语句实战(3)
前置 sql 语句 用来创建表.插入数据 ; DROP TABLE IF EXISTS dept_;-- 部门表 DROP TABLE IF EXISTS emp_;-- 部门表 ; SELECT @ ...
- 码农高效率工作必备工具之 StrokesPlus
鲁迅先生曾经说过:不想偷懒的码农不是好码农. 我今天偏偏就勤奋一下,把压箱底的偷懒神器分享给大家. StrokesPlus(简称S+)是一款非常好用的鼠标手势软件,通过按下鼠标键画手势,或者按快捷键, ...
- Js调用Android回调处理
通常在混合app中经常会使用js调用native的方法,一般是: window.nativeApp.call(XXX); 直接调用native方法,对于简单的处理倒是可以,如果需要回调呢?期待的方式是 ...
- android 百度地图v3.2.0获取实际地址
百度地图升级到v3.2.0后,api发生挺大的变化的,但是下载的Demo却不是最新版本的. 在v3.2.0之前获取详细地址只要:option.setIsNeedAddress(true); 但是升级后 ...
- Vue+Vuex实现自动登录 升级版
Vue+Vuex实现自动登录 升级版 之前实现的版本在这里:Vue+Vuex实现自动登录 在之前实现的版本中,如果你进行测试,可以看到在浏览器的local Storage中,确实里面有了我 ...
- React实践debug:JSX输出的限制(存疑)
今天在练习React构建组件的时候遇到一个问题. 由于文档中反复提倡将组件尽可能按功能单位分解复用.在练习用React做一个todolist时候,我把todolist分解成两部分: class Tod ...
- Spring Boot 教程(1) - HelloWorld
Spring Boot 教程 - HelloWorld 1. Spring Boot 的由来 大家都知道,Spring框架是Java生态中举足轻重的轻量型框架,帮助我们广大的大佬们进行Java开发.S ...
- eclipse——Error exists in required project Proceed with launch?
运行java文件时报错: Error exists in required project Proceed with launch? 报错截图: 问题参生原因:开始Buildpath了一个jar ...
- 组件-vue自定义方法传递
组件样式 面包屑导航栏 js Vue.component('bannerOne', { created() { console.log(this.bigbackColor); }, props: { ...