Advertisement

2021第十二届蓝桥杯省赛真题:路径

阅读量:

文章目录

    • 试题 D :路径
      • 【问题描述】
      • 【思路】
      • 【代码】
      • 【结果】
      • 【做题链接】

试题 D :路径

类型:结果填空,总分:10分

【问题描述】

小蓝掌握了最短路径算法后感到非常激动,并构造了一个特殊的图结构以寻找其中的最短路径。这个图包含2021个节点依次编号为1至2021对于任意两个不同的节点a和b如果它们之间的差值绝对值超过21则它们之间没有连线;反之如果差值绝对值不超过21则它们之间有一条无向边其长度为a与b的最小公倍数。例如节点1与节点23之间没有连线而节点3与节点24之间存在一条无向边其长度为24此外节点15与节点25之间也有一条无向边其长度为75请计算节点1到节点2021之间的最短路径长度是多少

【思路】

  1. 最短路径模板题,直接用朴素Dijkstra 就行,挖坑俺有空再总结一下最短路算法
  2. 注意图的构造,求最大公约数和最小公倍数老熟人了
  3. 发现另一种思路大佬的dp做法
  4. 错误记录 :在用邻接矩阵存图的时候,我们一般会用一个自定义的无穷大的数代表两点之间不连通,c/c++中一般会写memset(dist, 0x3f, sizeof dist);,我一开始考虑用Java的Integer.MAX_VALUE代表无穷大,但是我忽略了这样就不能计算了,因为Integer.MAX_VALUE随便加上一个数就超出int的表示范围结果就成负数(补码)了,所以注意无穷大还是得用static final int INF = 0x3f3f3f3f;0x3f3f3f3f的优点有:十进制为1061109567,和Integer.MAX_VALUE一个数量级,即10^9数量级,而一般场合下的数据都是小于10^9的。 0x3f3f3f3f * 2 = 2122219134,我们定义的这个无穷大相加依然不会溢出。

【代码】

复制代码
    import java.util.Scanner;
    import java.util.Arrays;
    
    public class Main {
    static final int INF = 0x3f3f3f3f;
    static final int N = 2030;
    static int[][] g = new int[N][N];
    static int[] dist = new int[N];
    static boolean[] s = new boolean[N];
    public static void main(String[] args) {
        //初始化图和距离
        for(int i = 1; i <= 2021; i++) {
            for(int j = i; j <= 2021; j++) {
                if(j - i > 21) {
                    g[i][j] = g[j][i] = INF;
                } else {
                    g[i][j] = g[j][i] = lcm(i, j);
                }
            }
        }
        Arrays.fill(dist, INF);
        dist[1] = 0;
    
        //朴素DijKstra
        for(int i = 1; i <= 2021; i++) {
            int v = -1;
            for(int j = 1; j <= 2021; j++) {
                if(!s[j] && (v == -1 || dist[v] > dist[j])) {
                    v = j;
                }
            }
            s[v] = true;
            for(int j = 1; j <= 2021; j++) {
                dist[j] = Math.min(dist[j], dist[v] + g[v][j]);
            }
        }
    
        System.out.println(dist[2021]);
    }
    
    //求最大公约数
    public static int gcd(int a, int b) {
        //递归方式性能差些,但是写法简单
        //return b == 0 ? a : gcd(b, a % b);
        int t;
        while(b != 0) {
            t = a % b;
            a = b;
            b = t;
        }
        return a;
    }
    //求最小公倍数
    public static int lcm(int a, int b) {
        return a * b / gcd(a, b);
    }
    }
    
    
    java
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-18/ALqSQZzCE2vdG1kWmUOTY8fbM0Pu.png)

【结果】

10266837

【做题链接】

https://www.lanqiao.cn/problems/1460/learning/

水平有限不保证对,欢迎各位大佬评论交流

全部评论 (0)

还没有任何评论哟~