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

来源:互联网 发布:mac魔兽世界多少g 编辑:程序博客网 时间:2024/06/16 15:56

摘要:求解所有节点的最短路完全可以用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 100000void 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;}

这里写图片描述

0 0
原创粉丝点击