寻飞机最短路径java_最短路径——dijkstra算法(Java)

本文介绍了Dijkstra算法用于解决有权图中最短路径问题,通过邻接矩阵和辅助矩阵实现。文章以PAT1003应急救援问题为例,展示算法的应用,并提供了完整的Java代码实现。
摘要由CSDN通过智能技术生成

在刷题的过程中常常会遇到求最短路径的问题,在求无权图的问题中我们常常使用BFS来求其最短路径,而BFS无法解决网(有权图)中的问题,我们解决网中的最短路径常常使用dijkstra算法来求解。

dijkstra算法是一种贪心的思想,具体其正确性的证明,这里就不再赘述。下面来直接讲解如何使用dijkstra算法:

1.我们在使用dijkstra算法时为了其编写的便捷性一般使用邻接矩阵来描述一个图。并将邻接矩阵中每个元素的值初始化为无穷大(或者很大很大的值)。之后根据图中的结构加入数字,称这个矩阵为E[][]。如下:

ebffd953e7881022d4d9e6514e2f5120.png

2.接下来我们还需要3个矩阵,分别为dist[] , collected[] , path[] 。dist用来存放遍历节点的距离信息,初始化为所求节点到其他各点的距离信息;collected[]用来存放是否dist中收录过该节点,初始化为false ;path[]用来存放路径,初始化为-1 。

690cbfc737d1a713067361760853e982.png

3. dijkstra算法的具体过程的伪代码如下:

public void dijkstra(boolean collected[],int[] dist,int[][] E,int[] path)

{

while(1)

{

v = collected[]为false的点中dist[]值最小的顶点;

if(v不存在) break ;

collected[v] = true ;

for(v顶点的每个邻接点w)

if(collected[w] == false)

{

if(dist[v] + E[v][w] < dist[w])

{

dist[w] = dist[v] + E[v][w] ;

path[w] = v ;

}

}

}

}

以上为dijkstra算法的基本过程,下面选一道dijkstra算法的题目来具体解释一下:

PAT1003

1003 Emergency (25 分)

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input Specification:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C​1​​ and C​2​​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c​1​​, c​2​​ and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C​1​​ to C​2​​.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2​​, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input:

5 6 0 2

1 2 1 5 3

0 1 1

0 2 2

0 3 1

1 2 1

2 4 1

3 4 1

Sample Output:

2 4

(大家自己翻译吧……)

这道题目很明显是要求我们求出有多少种距离相同的最短路径,同时他还要求一个最多的人员数

完整代码如下:

import java.util.*;public classMain {public static voidmain(String args[])

{

Scanner scanner= newScanner(System.in);int cities =scanner.nextInt();int roads =scanner.nextInt();int start =scanner.nextInt();int end =scanner.nextInt();int[] dis = new int[cities];int[][] map = new int[roads][roads];boolean[] set = new boolean[cities];int[] weigh = new int[cities] ;int[] w = new int[cities];int[] num = new int[cities] ;for(int i = 0 ; i < cities ; i ++)

{

Arrays.fill(map[i],9999999);

}

Arrays.fill(dis,9999999);for(int i = 0 ; i < cities ; i ++)

{

weigh[i]=scanner.nextInt();

}for(int i = 0 ; i < roads ; i ++)

{int x =scanner.nextInt();int y =scanner.nextInt();int z =scanner.nextInt();

map[x][y]= map[y][x] =z;

}

scanner.close();

dis[start]= 0;

w[start]=weigh[start] ;

num[start]= 1;for(int i = 0 ; i < cities ; i ++)

{int index = -1;int min = 9999999;for(int j = 0 ; j < cities ; j ++)

{if(set[j] == false && dis[j]

{

min=dis[j];

index=j ;

}

}if(index == -1) break;

set[index]= true;for(int j = 0 ; j < cities ; j ++)

{if(set[j] == false && map[index][j] != 9999999)

{if(min + map[index][j]

{

dis[j]= min +map[index][j] ;

num[j]=num[index] ;

w[j]= w[index] +weigh[j] ;

}else if(min + map[index][j] ==dis[j])

{

num[j]= num[j] +num[index] ;if(w[index] + weigh[j] >w[j])

{

w[j]= w[index] +weigh[j] ;

}

}

}

}

}

System.out.print(num[end]+ " " +w[end]);

}

}

下面我们来逐步分析:

1.读取数据以及构建邻接矩阵:

Scanner scanner = new Scanner(System.in);

int cities = scanner.nextInt();

int roads = scanner.nextInt();

int start = scanner.nextInt();

int end = scanner.nextInt();

int[] dis = new int[cities]; //构建dist[]

int[][] map = new int[roads][roads]; //邻接矩阵E

boolean[] set = new boolean[cities];  //collected[]

int[] weigh = new int[cities] ;    //记录每个城市救援队的数目

int[] w = new int[cities];       //到达每个城市的救援队的最多数量

int[] num = new int[cities] ;     //相同距离有多少种走法

for(int i = 0 ; i < cities ; i ++)  //初始化邻接矩阵

{

Arrays.fill(map[i], 9999999);

}

Arrays.fill(dis, 9999999);

for(int i = 0 ; i < cities ; i ++)   //初始化每个城市的救援队

{

weigh[i] = scanner.nextInt();

}

for(int i = 0 ; i < roads ; i ++)   //记录邻接矩阵

{

int x = scanner.nextInt();

int y = scanner.nextInt();

int z = scanner.nextInt();

map[x][y] = map[y][x] = z;

}

scanner.close();

2.使用dijkstra算法求最短路径:

dis[start] = 0 ; //起点到七点的距离为0

w[start] = weigh[start] ;

num[start] = 1 ;  //初始化起点的走法有一种

for(int i = 0 ; i < cities ; i ++)

{

int index = -1 ;

int min = 9999999;

for(int j = 0 ; j < cities ; j ++)

{

if(set[j] == false && dis[j] < min) //寻找dist[]中没有被收录的最小元素

{

min = dis[j];

index = j ;

}

}

if(index == -1) break ; //如果没有最小元素,则说明最短路径已经寻找完毕

set[index] = true ; //collected[]设置为true 表示已经收录该节点

for(int j = 0 ; j < cities ; j ++) //查找v相邻元素的距离

{

if(set[j] == false && map[index][j] != 9999999)

{

if(min + map[index][j] < dis[j])

{

dis[j] = min + map[index][j] ; //更新最短距离

num[j] = num[index] ; //更新走法

w[j] = w[index] + weigh[j] ;  //记录最短距离的救援队的数目

}

else if(min + map[index][j] == dis[j])  //当最短距离相同时

{

num[j] = num[j] + num[index] ;  //距离相同时,更新走法

if(w[index] + weigh[j] > w[j])

{

w[j] = w[index] + weigh[j] ;  //距离相同时救援队记录最多的那个 }

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值