单源最短路径(Dijkstra算法)

题目内容:
 有5个城市(A,B,C,D,E),其中每个城市到其他城市的直达距离已知,两个城市之间只有一条公路。计算从城市A到其他任意城市的最短路径距离。
输入描述
4行数据, 第一行是A到(B,C,D,E)的直达距离,第二行是B到(C,D,E)的直达距离,。。。,第4行是D到E的直达距离。

输出描述
A城市到(B,C,D,E)的最短距离。

输入样例
2 3 4 5  
3 4 2 
4 3   
3

输出样例

2 3 4 4


(1)解题思路:

  利用Dijstra算法,将问题变化为一个适合贪心算法的子集选择问题。

  定义M为一个城市集合:其中每个城市X,存在一条从源点A城市到X的全局最短路径,并且该最短路径不包含A之外的城市。

①(即:当城市集合M = {A}时,该题目中的初始dis[] = {0, 2, 3, 4, 5})

  定义N = 全部城市-M集合,需要从N中选择一个城市X进入M集合。此时在dis[]中选择最短的路径,即min = 2, minpos = B(即哪个城市);

  根据所选择的第二个点X = B,此时城市集合M = {A, B},在此时更新从A到任意一个城市是否经过B点的最短路径


②(M= {A, B}, 更新后dis[] = {0, 2, 3, 4, 4})

  再在dis[]中选择最短的路径,即min = 3, minpos = C;

  根据所选择的第二个点X = C,此时城市集合M = {A, B, C},在此时更新从A到任意一个城市是否经过C点的最短路径



③(M= {A, B, C},更新后dis[] = {0,2, 3, 4, 4})

  再在dis[]中选择最短的路径,即min = 4, minpos = D;

  根据所选择的第二个点X = D,此时城市集合M = {A, B, C, D},在此时更新从A到任意一个城市是否经过D点的最短路径




④(M= {A, B, C,D}, 更新后dis[] = {0, 2, 3, 4, 4})

  再在dis[]中选择最短的路径,即min = 4, minpos = E;

  根据所选择的第二个点X = E,此时城市集合M = {A, B, C, D, E},在此时更新从A到任意一个城市是否经过E点的最短路径




⑤(M= {A, B, C,D, E}, 更新后dis[] = {0, 2, 3, 4, 4})

   输出答案为A→B, A→C, A→D, A→E 即(2, 3, 4, 4).

(2)其中利用的两个定理:

1.如果从u→v点的最短路径L={u, , x, , y, , v}, 则L上的子段l= (x, , y)也是最短路径。

2.所有N中的顶点中,最短的局部最短路径是全局最短路径。

(3)证明:略


代码:

#include <iostream>
#define INFINITE 0x7fffffff
using namespace std;

int main() {

	int dis[5] = { 0 };
	bool inM[5] = { 0 };//表示是否已进入M集合
	int cost[5][5] = { 0 };
	for(int i = 0; i < 5; i++)
		for (int j = 0; j < 5; j++)
		{
			if (i < j)
				cin >> cost[i][j];
			cost[j][i] = cost[i][j];
		}//输入

	for (int i = 0; i < 5; i++)
		dis[i] = cost[0][i];//第1步的dis[]

	inM[0] = 1;//第一个城市A自然是进入了M集合

	for (int i = 1; i <= 4; i++)
	{
		int min = INFINITE;
		int minpos = 0;
		for(int j = 0; j < 5; j++)
			if (inM[j] == 0 && dis[j] < min) {
				//没有进入M集合的并且路径最短
				min = dis[j];
				minpos = j;
			}
		inM[minpos] = 1;
		for(int j = 0; j < 5; j++)
			if (inM[j] == 0 && dis[j] > dis[minpos] + cost[minpos][j])
				dis[j] = dis[minpos] + cost[minpos][j];
			//是否经过这个minpos,更新dis[]
	}
	for (int i = 1; i < 5; i++)
		cout << dis[i] << " ";//输出
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_37430374/article/details/78292944