所有节点之间的最短路问题

摘要:求解所有节点的最短路完全可以用v次Dijkstra算法来解决,但是动态规划提供了一种新的思路同样以O(|v|^3)的时间界解决问题,同时因为循环更加紧凑,实际效率要快的多.

基本思路:

【1】首先要考虑动态规划是的状态空间是一个点集和起始点与终点.

【2】假设 Dijk 代表从i到j只用0到k个节点作为中间节点,D[i][j]代表i到j的最短路径.那么 Dijk = min{ Dij(k1),D[i][k]+D[k][j] },也就是是最小的路径总是在新加入的点或者以前的点集中产生.D[i][j] = Dijv ,(v代表全部节点).很显然这需要三重循环来计算所有点之间的最短路径.

[3]现在要考虑如何来构建循环,实际上,我们计算 Dijk 之前必须知道 Dij(k1) ,所以k应该放在所有循环的最外面.然后里面两重循环是i,j。

[4]那么 Dij(k1) 是如何被计算的呢?,这是循环里面的核心内容,首先我们需要一个邻接矩阵用来存储相邻节点之间的距离.在一个双重内循环里面,考虑一开始的值k=0,我们只用节点0作为中间节点,对于所有的D[i][j],D[i][j] = Min(C[i][j],D[i][k]+D[k][j]),假如存在这样只含有节点0的中间节点的最短通路就被计算出来了.接着,当k=1的时候,我们计算D[i][j] = Min(D[i][j],D[i][k]+[k][j])。如果对于某一对(i,j),存在只包含了中间节点0,1的最短路径,那么D[i][j]代表的是只通过节点0的路径或者是没有通过节点的路径,而D[i][k] + D[k][j]则体现了通过了节点1的路径.

【5】这里有一个问题,那就是D[i][k]与D[k][j]是否已经代表i到k的最短路径?即是否已经被及时更新了呢?其实可以这样理解,在第一次k=0,的循环中,D[i][1]与D[1][i]也是作为最短路径被计算过的,如果它们之间能够通过0或者直接相邻,那么它们也将被计算出来(而不是Infinity).综上分析,在第k次循环中,前k-1个中间节点必然被计算出来,而且起始点i到新的中间点k的路径D[i][k]如果只通过(节点0…..k-1)和相对应的D[k][j]都将被计算出来.

#include "stdafx.h"
#define N 5
#define Notvertex -1
#define Infinity 100000
void allpairs(int A[][N],int D[][N],int path[][N])
{
    int k,i,j;

    for( i = 0;i<=N-1;i++)
        for(j = 0;j<=N-1;j++)
        {
            D[i][j] = A[i][j];
            path[i][j] = Notvertex;
        }
    for(k = 0;k<=i-1;k++)
    {
        for( i = 0;i<=N-1;i++)
        for(j = 0;j<=N-1;j++)
        {
            if (D[i][k]+D[k][j]<D[i][j])
            {
            D[i][j] = D[i][k]+D[k][j];
            path[i][j] = k;
            }
        }
    }
}
void Printpath(int A[][N],int path[][N],int start, int end )//输出路径
{
    int k = path[start][end];
     if(A[start][k] != Infinity)//相邻
    {
        printf("to %d ",end);
    }
     else if (k!=Notvertex)//不相邻但可达
     {
         Printpath(A,path,start,k);
         printf("to %d ",end);
     }
}
void Print(int A[][N],int path[][N],int start, int end )
{
    int k = path[start][end];
    if(k ==Notvertex&&A[start][end]== Infinity)//不可达
    {
    printf("error : not available");
    return;
    }
    printf(" %d ",start);
    Printpath(A,path,start,k);
    Printpath(A,path,k,end);
}
int _tmain(int argc, _TCHAR* argv[])
{
    int i,j;
    int A[N][N] = {0},D[N][N],path[N][N];
    for( i = 0;i<=N-1;i++)
        for(j = 0;j<=N-1;j++)
        {
            if(i == j)
                A[i][j] = 0;
            else
            A[i][j] = Infinity;
        }
        A[0][2] = 100;
        A[0][1]  = 2;
        A[1][3]  = 3;
        A[3][4]  = 2;
        A[4][2]  = 2;
        allpairs(A,D,path);
        Print(A,path,0,2);
    return 0;
}

这里写图片描述

你可能感兴趣的:(算法,动态规划)