第十二届蓝桥杯真题Java B组 【路径】

题目描述:
小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。
小蓝的图由2021 个结点组成,依次编号1 至2021。
对于两个不同的结点a, b,如果a 和b 的差的绝对值大于21,则两个结点之间没有边相连;
如果a 和b 的差的绝对值小于等于21,则两个点之间有一条长度为a 和b 的最小公倍数的无向边相连。
例如:结点1 和结点23 之间没有边相连;结点3 和结点24 之间有一条无向边,长度为24;
结点15 和结点25 之间有一条无向边,长度为75。
请计算,结点1 和结点2021 之间的最短路径长度是多少。
提示:建议使用计算机编程解决问题。

思路:
本题考最短路径和最小公倍数。
最小公倍数由两数之积除以他们的最大公约数得到
采用Dijkstra算法,每次加入一个点,更新最短路径,直至得到起点到终点的最小值。

完整代码:

public class Main {
    static int inf = Integer.MAX_VALUE;     //  定义没有路径时的距离表示
    public static void main(String[] args) {
        int[][] node = new int[2022][2022]; //  用二维数组存放两点之间的距离
        for (int i=1;i<=2021;i++){
            for (int j=1;j<=2021;j++){
                if (i==j)                   //  到自己的距离为0
                    node[i][j] = 0;
                else if (Math.abs(i-j)>21)  //  两点之差大于21时,没有路径
                    node[i][j] = inf;
                else
                    node[i][j] = (i*j)/gcd(i,j); // 距离小于等于21,距离是最小公倍数
            }
        }
        int[] dijst = new int[2022];    //  表示dijst[i]表示1到i点的距离
        int[] visit = new int[2022];    //  visit[i]=1时,表示i点已加入点集
        for (int i=1;i<=2021;i++){
            dijst[i] = node[1][i];      //  初始化1到各点之间的距离
        }
        for (int i=1;i<2021;i++){
            int min = inf, index = 0;
            for (int j=2;j<=2021;j++){
                if (visit[j]==0&&dijst[j]<min){
                    min = dijst[j]; //  每次选择最短距离
                    index = j;      //  保存点的索引
                }
            }
            visit[index] = 1;   //  使vistt数组对应的索引为1
            for (int k=1;k<=2021;k++){      //  每加入一个点,就将1到所有点最小距离更新
                if (node[index][k]<inf){    //  当辅助点之间有路径时才做修改
                    if (dijst[k]>dijst[index]+node[index][k])   //  若1到k之间的距离小于1到辅助点,再到k的距离
                        dijst[k]=dijst[index]+node[index][k];   //  就更新1到k的最短距离
                }
            }
        }
        System.out.println(dijst[2021]);
    }
    private static int gcd(int a, int b){	//	求最大公约数的函数
        return b==0?a:gcd(b,a%b);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Easenyang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值