蓝桥杯2021年真题演练——4、路径(JavaA组)

上一题:3、货物摆放(JavaA组)

题目大意

在这里插入## 标题图片描述
答案: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);
    }
}

在这里插入图片描述

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值