您的位置:首页 > 其它

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

2016-11-14 17:46 477 查看
题目

给定如图所示的无向连通图,嘉定图中所有边的权值都为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

)
{
int step
; // 每个结点第几步可以到达
int stepNumber
; // 每个结点有几种走法
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

;
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外,然后根据上面介绍过的方法更新数组,这样保证已经遍历过的结点是正确的,那么在正确的结点基础上去推理其他结点,也应该是正确的,其实我感觉这个也是动态规划的思想
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: