例题链接:
先展示代码:
package daily_Test.test0422;
//样例输入
import java.util.*;
//3 4
// 1 3 9
// 1 2 3
// 1 2 1
// 2 3 2
// 1 3 1
public class DijkstraAndA_Star {
static List<int[]>[] lists;
static List<int[]>[] lists2;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
lists = new List[n + 1];
lists2 = new List[n + 1];
for (int i = 0; i <= n; i++) {
lists[i] = new ArrayList<>();
lists2[i] = new ArrayList<>();
}
for (int i = 0; i < m; i++) {
int o1 = sc.nextInt();
int o2 = sc.nextInt();
int len = sc.nextInt();
lists[o2].add(new int[]{o1, len});
lists2[o1].add(new int[]{o2,len});
}
int a = sc.nextInt();
int e = sc.nextInt();
int k = sc.nextInt();
int[] res = Dijkstra(e,lists);
int ans = A_Star(lists2,a,e,k,res);
System.out.println(ans);
}
private static int A_Star(List<int[]>[] lists2, int start, int end, int k, int[] expect) {
PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2)->{
return o1[0] - o2[0];
});
int count = 0;
pq.offer(new int[]{expect[start],start,0});
while (!pq.isEmpty()){
int[] a = pq.poll();
int e = a[0],node = a[1],l = a[2];
if(node == end){
count++;
if(count == k){
return node;
}
}
for(int[] next:lists2[node]){
pq.offer(new int[]{e+expect[next[0]]+next[1],next[0],l+next[1]});
}
}
return -1;
}
private static int[] Dijkstra(int target, List<int[]>[] lists) {
int[] arr = new int[lists.length+1];
Arrays.fill(arr,Integer.MAX_VALUE);
arr[0] = 0;
arr[target] = 0;
PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2)->{
return o1[1]-o2[1];
});
pq.offer(new int[]{target,0});
while (!pq.isEmpty()){
int[] a = pq.poll();
for(int[] b:lists[a[0]]){
if(a[1]+b[1]<arr[b[0]]){
arr[b[0]] = a[1]+b[1];
pq.offer(new int[]{b[0],arr[b[0]]});
}
}
}
return arr;
}
}
好的,下面为你详细讲解这段包含Dijkstra算法和A*算法实现的Java代码:
-
整体功能概述: 这段代码的主要目的是在一个加权有向图中,先使用Dijkstra算法计算出从一个特定目标节点到其他所有节点的最短距离,然后使用A*算法来找到从起始节点到目标节点的第
k短的路径。 -
代码结构分析:
-
包声明和导入:
package daily_Test.test0422; import java.util.*;声明了代码所在的包
daily_Test.test0422,并导入了java.util包,用于使用Scanner、List、PriorityQueue等工具类。 -
全局变量声明:
static List<int[]>[] lists; static List<int[]>[] lists2;声明了两个静态数组
lists和lists2,用于存储图的邻接表。lists存储的是反向边(即边的方向与实际相反),lists2存储的是正向边。 -
主函数
main:public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); lists = new List[n + 1]; lists2 = new List[n + 1]; for (int i = 0; i <= n; i++) { lists[i] = new ArrayList<>(); lists2[i] = new ArrayList<>(); } for (int i = 0; i < m; i++) { int o1 = sc.nextInt(); int o2 = sc.nextInt(); int len = sc.nextInt(); lists[o2].add(new int[]{o1, len}); lists2[o1].add(new int[]{o2,len}); } int a = sc.nextInt(); int e = sc.nextInt(); int k = sc.nextInt(); int[] res = Dijkstra(e,lists); int ans = A_Star(lists2,a,e,k,res); System.out.println(ans); }-
首先,通过
Scanner读取输入的图的节点数n和边数m。 -
初始化
lists和lists2数组,并为每个索引位置创建一个ArrayList来存储邻接边。 -
读取每条边的信息(起始节点
o1、终止节点o2和边的长度len),并将其分别存储到lists和lists2中(lists存储反向边,lists2存储正向边)。 -
读取起始节点
a、目标节点e和要找的第k短路径的k值。 -
调用
Dijkstra算法计算从目标节点e到其他所有节点的最短距离,结果存储在res数组中。 -
调用
A_Star算法,传入正向边的邻接表lists2、起始节点a、目标节点e、k值以及res数组,获取第k短路径的结果ans并输出。
-
-
Dijkstra算法实现函数
Dijkstra:private static int[] Dijkstra(int target, List<int[]>[] lists) { int[] arr = new int[lists.length+1]; Arrays.fill(arr,Integer.MAX_VALUE); arr[0] = 0; arr[target] = 0; PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2)->{ return o1[1]-o2[1]; }); pq.offer(new int[]{target,0}); while (!pq.isEmpty()){ int[] a = pq.poll(); for(int[] b:lists[a[0]]){ if(a[1]+b[1]<arr[b[0]]){ arr[b[0]] = a[1]+b[1]; pq.offer(new int[]{b[0],arr[b[0]]}); } } } return arr; }-
初始化一个数组
arr来存储从目标节点到其他所有节点的最短距离,初始值为Integer.MAX_VALUE,并将目标节点到自身的距离设为0。 -
创建一个优先队列
pq,按照距离从小到大排序。将目标节点及其距离0加入优先队列。 -
当优先队列不为空时,取出队首元素
a(包含节点编号和到目标节点的距离)。 -
遍历该节点的所有邻接节点
b,如果通过当前节点a到达邻接节点b的距离更短,则更新arr[b[0]]的值,并将邻接节点b及其新的距离加入优先队列。 -
最终返回存储最短距离的数组
arr。
-
-
A*算法实现函数
A_Star:private static int A_Star(List<int[]>[] lists2, int start, int end, int k, int[] expect) { PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2)->{ return o1[0] - o2[0]; }); int count = 0; pq.offer(new int[]{expect[start],start,0}); while (!pq.isEmpty()){ int[] a = pq.poll(); int e = a[0],node = a[1],l = a[2]; if(node == end){ count++; if(count == k){ return node; } } for(int[] next:lists2[node]){ pq.offer(new int[]{e+expect[next[0]]+next[1],next[0],l+next[1]}); } } return -1; }-
创建一个优先队列
pq,按照评估函数值从小到大排序。评估函数值为当前节点到起始节点的距离加上估计的到目标节点的距离(使用expect数组中的值)。 -
初始化计数器
count为0,将起始节点及其评估函数值和到起始节点的距离0加入优先队列。 -
当优先队列不为空时,取出队首元素
a(包含评估函数值、节点编号和到起始节点的距离)。 -
如果当前节点是目标节点,则
count加1,当count等于k时,返回目标节点编号。 -
遍历当前节点的所有邻接节点
next,计算邻接节点的评估函数值,并将其加入优先队列。 -
如果遍历完所有节点仍未找到第
k短路径,则返回-1。
-
-
希望以上讲解能帮助你理解这段代码中Dijkstra算法和A*算法的实现逻辑。
1716

被折叠的 条评论
为什么被折叠?



