算法学习-最短路径条数问题(队列相关)

来源:互联网 发布:淘宝数据采集器免费 编辑:程序博客网 时间:2024/05/22 04:24

题目

给定如图所示的无向连通图,嘉定图中所有边的权值都为1,显然,从原点A到终点T的最短路径有多条,求不同的最短路径的数目。


分析

权值相同的最短路径问题,则单元点Dijkstra算法退化成BFS广度优先搜索,假定起点为0,终点为N:

结点步数step[0...N-1]初始化为0,记录从A到其他结点的最短路径的步数

路径数目pathNum[0...N-1]初始化为0,记录从A到其他结点的最短路径的条数

pathNum[0]=1,从A到A有1条


若从当前结点i扩展到邻接结点j时有以下两种情况

1、step[j] == 0,这种情况意味着还有有任何路径到达j所以此时到达j的最短路径为到达i的最短路径加1,到达j的最短路径的条数即为到达i的最短路径的条数

即step[j] = step[i] + 1; pathNum[j] = pathNum[i];

2、step[j] == step[i] + 1,则说明出了通过i以外已经有别的路径到达了j,而且所用步数和这个相同,所以这时候这时候到达j的最短路径为到达i的最短路径就不需要变化,到达j的最短路径的条数等于原来的条数在加上到达i的最短路径的条数

即pathNum[j] += pathNum[i]; 


代码如下

// suanfa1.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <stdlib.h>#include <queue>const int N = 16;int Calc(int G[N][N]){int step[N];    // 每个结点第几步可以到达int stepNumber[N];   // 每个结点有几种走法memset(step, 0, sizeof(int) * N);memset(stepNumber, 0, sizeof(int) * N);stepNumber[0] = 1;std::queue<int> q;   // 当前搜索结点q.push(0);int from, i, s;while (!q.empty()){from = q.front();q.pop();s = step[from] + 1;for (i = 1; i < N; i++)         // 0是起点,不遍历{if (G[from][i] == 1)      // 连通{// i尚未可达或发现更快的路(权值不同才可能)if ((step[i] == 0) || (step[i] > s)){step[i] = s;stepNumber[i] = stepNumber[from];q.push(i);}else if (step[i] == s)  // 发现相同长度的路径{stepNumber[i] += stepNumber[from];}}}}return stepNumber[N - 1];}int _tmain(int argc, _TCHAR* argv[]){int G[N][N];memset(G, 0, sizeof(int) * N * N);G[0][1] = G[0][4] = 1;G[1][5] = G[1][0] = G[1][2] = 1;G[2][1] = G[2][6] = G[2][3] = 1;G[3][2] = G[3][7] = 1;G[4][0] = G[4][5] = 1;G[5][1] = G[5][4] = G[5][6] = G[5][9] = 1;G[6][2] = G[6][5] = G[6][7] = G[6][10] = 1;G[7][3] = G[7][6] = 1;G[8][9] = G[8][12] = 1;G[9][8] = G[9][13] = G[9][10] = 1;G[10][9] = G[10][14] = G[10][11] = 1;G[11][10] = G[11][15] = 1;G[12][8] = G[12][13] = 1;G[13][9] = G[13][12] = G[13][14] = 1;G[14][10] = G[14][13] = G[14][15] = 1;G[15][11] = G[15][14] = 1;std::cout<<Calc(G)<<std::endl;system("pause");return 0;}

详细介绍一下改程序的执行过程

用队列来记录将要作为当前的结点,如果结点处理过,则弹出队列,这保证了他是广度搜索,处理每一个结点的时候会遍历图中所有结点,除0外,然后根据上面介绍过的方法更新数组,这样保证已经遍历过的结点是正确的,那么在正确的结点基础上去推理其他结点,也应该是正确的,其实我感觉这个也是动态规划的思想



1 0