LQ0083 路径Dijkstra算法

Posted 海岛Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LQ0083 路径Dijkstra算法相关的知识,希望对你有一定的参考价值。

题目来源:蓝桥杯2021初赛 C++ A组D题

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

提示:建议使用计算机编程解决问题

问题分析
最短路问题,可以用Dijkstra算法或Floyd算法来解决。
后者太慢,需要先算出结果后直接输出结果,是杀鸡用牛刀的解法。
用Dijkstra算法来解决是正解。

AC的C++语言程序(Dijkstra算法)如下:

/* LQ0083 路径 */

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

/* Dijkstra算法
 * 复杂度:O(N×N)
 * 输入:n 全局变量,图结点数
 *      g 全局变量,邻接矩阵,g[i][j]表示结点i到j间的边距离
 * 输出:dis 全局变量,dis[i]表示结点1到i的最短距离
 */
const int INF = 0x3f3f3f3f;
const int N = 2021;
int dis[N + 1], g[N + 1][N + 1], n, vis[N + 1];

void dijkstra()

    memset(dis, INF, sizeof dis);
    memset(vis, 0, sizeof vis);

    dis[1] = 0;
    for(int i = 1; i <= n; i++) 
        int mark = -1, mindis = INF;
        for(int j = 1; j <= n; j++)
            if(!vis[j] && dis[j] < mindis)
                mindis = dis[j], mark = j;
        vis[mark] = 1;
        for(int j = 1; j <= n; j++)
            if(!vis[j])
                dis[j] = min(dis[j], dis[mark] + g[mark][j]);
    


int main()

    n = N;
    memset(g, INF, sizeof g);
    for(int i = 0; i <= n; i++)
        g[i][i] = 0;

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (abs(i - j) <= 21)
                g[i][j] = g[j][i] = i * j / __gcd(i, j);

    dijkstra();

    cout << dis[n] << endl;

    return 0;

AC的C++语言程序(Floyd算法)如下:

/* LQ0083 路径 */

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

/* Floyd-Warshall算法:计算图中任意2点之间的最短距离
 * 复杂度:O(N×N×N)
 * 输入:n 全局变量,图结点数
 *      g 全局变量,邻接矩阵,g[i][j]表示结点i到j间的边距离
 * 输出:g 全局变量
 */
const int INF = 0x3f3f3f3f;
const int N = 2021;
int g[N +1][N + 1], n;

void floyd()

    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);


int main()

//    memset(g, INF, sizeof g);

//    n = N;
//    for (int i = 1; i <= n; i++)
//        for (int j = 1; j <= n; j++)
//            if (abs(i - j) <= 21)
//                g[i][j] = g[j][i] = i * j / __gcd(i, j);

//    floyd();

//    cout << g[1][n] << endl; // 10266837

    cout << 10266837 << endl;

    return 0;

以上是关于LQ0083 路径Dijkstra算法的主要内容,如果未能解决你的问题,请参考以下文章

Java数据结构 最短路径解法Dijkstra算法

1003 Emergency(Dijkstra,Bellman-Ford,SPFA三种解法)

dijkstra算法怎么记录路径

1.Dijkstra算法求解格栅地图路径matlab代码

1.Dijkstra算法求解格栅地图路径matlab代码

1.Dijkstra算法求解格栅地图路径matlab代码