【动态规划】最短路径问题Floyd算法

Floyd算法是求加权图最短路径的经典算法之一,利用了动态规划的思想解决。

算法描述
最短路径问题:
设有一加权图G,从G中某个顶点出发达到另一个顶点,所经过边的权值之和最小的路径,被称为最短路径。

Floyd算法是解决加权图(图可以是有向也可以是无向,可以存在负权)中任意两点之间的最单路径的一种算法。

基本思路:

通过Floyd算法计算最短路径时,图一般采用二维数组,邻接矩阵的形式进行存储。
首先对邻接矩阵进行初始化,在图G中,g[i][j g[i][jg[i][j]表示从顶点i到顶点j的直接路径(权值);若i和j不相邻,即无直接连线,则置g[i][j]=∞ g[i][j]= ∞g[i][j]=∞;且设g[i][i]=0 g[i][i]=0g[i][i]=0,即顶点i到顶点i的距离为0;
寻找最短距离的过程就是对邻接矩阵进行更新的过程:若从顶点i到顶点j经过顶点k,且g[i][j]>g[i][k]+g[k][j] g[i][j] > g[i][k] + g[k][j]g[i][j]>g[i][k]+g[k][j],则从i到j的最短距离更新为从i到k再到j;
对图进行n次更新,遍历i,j,k的值,找到最短路径;
从上面我们可以看到Floyd算法的时间复杂度为O(n3)。

源代码运行结果参照此图

源代码
#include <iostream>
#include <vector>

#define MAX 9999
using namespace std;

//弗洛伊德算法
void Floyd(vector<vector<int> > &g, vector<vector<int> > &p) {
    int n = g.size();    //图的顶点数+1
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < n; j++) {
            if (i == j)    //相同顶点
                continue;
            for (int k = 1; k < n; k++) {
                if (g[i][j] > g[i][k] + g[k][j]) {    //从顶点i到j经过k,且dij > dik + dkj
                    g[i][j] = g[i][k] + g[k][j];
                    p[i][j] = k;
                }
            }
        }
    }
}

//打印路径
void printPath(vector<vector<int> > &p, int a, int b) {
    int k = p[a][b];
    if (k == -1)
        return;
    printPath(p, a, k);
    cout << "-> " << k;
    printPath(p, k, b);
}

int main() {
    int vexNum, edgeNum;
    cout << "输入顶点数量和边的数量:";
    cin >> vexNum >> edgeNum;
    //建立邻接矩阵并初始化
    vector<vector<int> > graph(vexNum + 1, vector<int> (vexNum + 1,MAX));    //图的邻接矩阵
    vector<vector<int> > path(vexNum + 1, vector<int>(vexNum + 1, -1));    //路径矩阵
    
    //初始化图
    for (int i = 1; i <= vexNum; i++)
        graph[i][i] = 0;
    cout << "输入邻接边及权值:(边a 边b 权值w)" << endl;
    for (int i = 0; i < edgeNum; i++) {
        int a, b, w;
        cin >> a >> b >> w;
        graph[a][b] = w;
    }

    Floyd(graph,path);        //弗洛伊德算法

    int a, b;
    cout << "输入你要查询的最短路径 a->b:(顶点a 顶点b)";
    cin >> a >> b;
    if (graph[a][b] == MAX)
        cout << "从" << a << "到" << b << "没有路径。" << endl;
    cout << "从" << a << "到" << b << "最短路径为:" << graph[a][b] << endl;
    cout << a;
    printPath(path, a, b);
    cout << "-> " << b << endl;

    system("pause");
    return 0;
}
 

猜你喜欢

转载自blog.csdn.net/ln1593570p/article/details/104714160