题目大意
答案:10266837
解题思路
⭐⭐数据结构学好了,这个题就没有任何问题,否则还是直接放弃吧
🌙首先要把这个图按规则存储起来,我们一般都用邻接矩阵,而且因为是无向图,所以这个矩阵是对称的。
🌙过程中还涉及到求最小公倍数,这里我们需要知道:对于俩个数n和m,他们的最小公倍数是lcm,最大公约数是gcd,则有:n×m=gcd×lcm 所以可以先通过辗转相除法求最大公约数,进一步求最小公倍数。
🌙图存好后可以直接使用迪杰斯特拉算法或者佛洛依德算法求最短路径
代码解析
⭐迪杰斯特拉算法
public class Main {
public static void main(String[] args) {
int len = 2021;
int maxValue=1000000000;
int[][] matrix = new int[len][len];
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
if (j <= 21 + i) {
matrix[i][j] = lcm(j + 1, i + 1);
matrix[j][i]=lcm(j + 1, i + 1);
}else{
matrix[i][j]=maxValue;
matrix[j][i]=maxValue;
}
}
}
dijstra( matrix, 0);
System.out.print("顶点1到顶点"+"len"+"的最短路径长度是:");
System.out.println(matrix[1-1][len-1]);
}
//最大公约数
public static int gcd(int m, int n) {
return n == 0 ? m : gcd(n, m % n);
}
//最小公倍数
public static int lcm(int m, int n) {
return m * n / gcd(m, n);
}
public static void dijstra(int[][] matrix, int source) {
//最短路径长度
int[] shortest = new int[matrix.length];
//判断该点的最短路径是否求出
int[] visited = new int[matrix.length];
//存储输出路径
String[] path = new String[matrix.length];
//初始化输出路径
for (int i = 0; i < matrix.length; i++) {
path[i] = new String(source + "->" + i);
}
//初始化源节点
shortest[source] = 0;
visited[source] = 1;
for (int i = 1; i < matrix.length; i++) {
int min = Integer.MAX_VALUE;
int index = -1;
for (int j = 0; j < matrix.length; j++) {
//已经求出最短路径的节点不需要再加入计算并判断加入节点后是否存在更短路径
if (visited[j] == 0 && matrix[source][j] < min) {
min = matrix[source][j];
index = j;
}
}
//更新最短路径
shortest[index] = min;
visited[index] = 1;
//更新从index跳到其它节点的较短路径
for (int m = 0; m < matrix.length; m++) {
if (visited[m] == 0 && matrix[source][index] + matrix[index][m] < matrix[source][m]) {
matrix[source][m] = matrix[source][index] + matrix[index][m];
path[m] = path[index] + "->" + m;
}
}
}
}
}
⭐弗洛伊德算法
public class Main {
public static void main(String[] args) {
int len = 2021;
int maxValue=1000000000;
int[][] matrix = new int[len][len];
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
if (j <= 21 + i) {
matrix[i][j] = lcm(j + 1, i + 1);
matrix[j][i]=lcm(j + 1, i + 1);
}else{
matrix[i][j]=maxValue;
matrix[j][i]=maxValue;
}
}
}
floyd(matrix);
System.out.print("顶点1到顶点"+"len"+"的最短路径长度是:");
System.out.println(matrix[1-1][len-1]);
}
public static void floyd(int[][] dis){
int length;
for (int k = 0; k <dis.length ; k++) {
for (int i = 0; i < dis.length; i++) {
for (int j = 0; j < dis.length; j++) {
length=dis[i][k]+dis[k][j];
if(length<dis[i][j]){
dis[i][j]=length;
}
}
}
}
}
//最大公约数
public static int gcd(int m, int n) {
return n == 0 ? m : gcd(n, m % n);
}
//最小公倍数
public static int lcm(int m, int n) {
return m * n / gcd(m, n);
}
}