Floyd(动态规划)求解任意两点间的最短路径(图解)

Posted TomoyaAT的技术分析屋~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Floyd(动态规划)求解任意两点间的最短路径(图解)相关的知识,希望对你有一定的参考价值。

Floyd算法的精髓在于动态规划的思想,即每次找最优解时都建立在上一次最优解的基础上,当算法执行完毕时一定是最优解

对于邻接矩阵w,w保存最初始情况下任意两点间的直接最短距离,但没有加入中继点进行考虑
如w[1][2]=20,即表示点1与点2的当前最短距离(直接距离)为20

对于路径矩阵path,保存了点i到点j的最短路径中下一个点的位置,
如path[1][2]=0,表示1->2的路径中的下一个点为结点0

Floyd算法对所有中继点在任意两点中进行循环遍历.即k从0-n时考虑(i->k,k->j)的路径是否小于(i->j)的路,如果小于即更新邻接矩阵w的值与path矩阵中的值,使其始终保持最短
图解如下:

代码用例:

代码如下

点击查看代码
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
const int MAX = 999;
class Solution {
public:
	void GetPath(vector<vector<int>>vec,int n) {
		
		vector<vector<int>>path(n);

		//初始化
		for (int i = 0; i != n; i++)
			path[i].resize(n);

		for(int i=0;i!=n;i++)
			for (int j = 0; j != n; j++) {
				if (vec[i][j] != MAX)path[i][j] = j;
				else path[i][j] = -1;
			}

		for (int i = 0; i < n; i++)path[i][i] = -1;
		for(int k=0;k!=n;k++)
			for(int i=0;i!=n;i++)
				for (int j = 0; j != n; j++) {
					if (vec[i][k] + vec[k][j] < vec[i][j]) {
						vec[i][j] = vec[i][k] + vec[k][j];
						path[i][j] = path[i][k];
					}
				}
				
		for (int i = 0; i != n; i++)
		{
			cout << "\\nStating from vertex: " << i << endl;
			bool flag = 0;
			for (int j = 0; j != n; j++)
				if (j != i && vec[i][j] < MAX) {
					flag = 1;
					cout << i << "->" << j << ":distance=" << vec[i][j] << ": " << i;
					int k = path[i][j];
					while (k != j) {
						cout << "->" << k;
						k = path[k][j];
					}
					cout << "->" << j << endl;
				}

			if (!flag)cout << "there\'s no path while starting from "<<i<<endl;
		}
	}
};
int main() {
	ifstream putIn("D:\\\\Input.txt", ios::in);
	int num;
	int finalCount = 0;
	putIn >> num;
	const int x = num;
	vector<vector<int>>myVector(num);
	//myVector:带权邻接矩阵
	for (int i = 0; i < num; i++)
		myVector[i].resize(num);
	for (int i = 0; i < num; i++)
		for (int j = 0; j < num; j++) {
			int temp;
			putIn >> temp;
			myVector[i][j] = temp;
		}
	Solution solution;
	cout << "Input文件中的邻接矩阵为\\n";
	for (auto x : myVector) {
		for (auto y : x)cout << y << \'\\t\';
		cout << endl;
	}
	solution.GetPath(myVector,num);
	return 0;
}

我是一个还没有想好写点啥的小尾巴

任意两点间的最短路问题 Floyd-Warshall算法

这一算法与之前的Bellman-F=Ford算法一样,都可以判断负环

只需要检查dp [i] [j] 是负数的顶点i即可

 

 1 // 求解任意两点间的最短路径问题
 2 // Floyed-Warshall算法
 3 // 复杂度O(N^3),N为顶点数
 4 
 5 #include <cstdio>
 6 #include <iostream>
 7 
 8 using namespace std;
 9 // 用dp的思路来求解
10 // dp[k][i][j]:从i到j,只利用前K个节点的最短路
11 // dp[k][i][j]=dp[k-1][i][k] + dp[k-1][k][j]
12 // 由于后一层所需的,都来自前一层,而前一层所需
13 // 然后在考虑循环顺序,定k,并且维护最小,所以中间元素必定使用之前维护的在k行k列的元素
14 // 而维护最小值时,k行k列元素,在循环中,加和一定大于原来的值(否则存在d[i][j]<0,存在负圈)
15 // 所以维护最小值时不更新,依旧是上一列表中的值
16 // 所以dp数组可以降维进行运算
17 
18 const int max_N = 200+2;
19 const int max_E = 10000+2;
20 const int INF = 1e9;
21 
22 int dp[max_N][max_N];
23 int N,E;
24 
25 void floyd_warshall()
26 {
27     for(int k=0;k<N;++k)
28     {
29         for(int i=0;i<N;++i)
30         {
31             for(int j=0;j<N;++j)
32             {
33                 dp[i][j]=min( dp[i][j],dp[i][k]+dp[k][j] );
34             }
35         }
36     }
37 }
38 
39 int main()
40 {
41     scanf("%d %d",&N,&E);
42     int a,b,c;
43     for(int i=0;i<N;++i)
44     {
45         for(int j=0;j<N;++j)
46         {
47             if(i==j)
48             {
49                 dp[i][j]=0;
50             }
51             else
52             {
53                 dp[i][j]=INF;
54             }
55         }
56     }
57     for(int i=0;i<E;++i)
58     {
59         scanf("%d %d %d",&a,&b,&c);
60         dp[a][b]=c;
61         // 无向图
62         dp[b][a]=c;
63     }
64     floyd_warshall();
65 
66     for(int i=0;i<N;++i)
67     {
68         for(int j=0;j<N;++j)
69         {
70             printf("%d ",dp[i][j]);
71         }
72         printf("
");
73     }
74     return 0;
75 }
76 /*
77 7 10
78 0 1 2
79 0 2 5
80 1 2 4
81 1 3 6
82 1 4 10
83 2 3 2
84 3 5 1
85 4 5 3
86 4 6 5
87 5 6 9
88 
89 
90 
91 
92 0 2 5 7 11 8 16
93 2 0 4 6 10 7 15
94 5 4 0 2 6 3 11
95 7 6 2 0 4 1 9
96 11 10 6 4 0 3 5
97 8 7 3 1 3 0 8
98 16 15 11 9 5 8 0
99 */

 

以上是关于Floyd(动态规划)求解任意两点间的最短路径(图解)的主要内容,如果未能解决你的问题,请参考以下文章

任意两点间的最短路问题 Floyd-Warshall算法

Floyd求解最短路

44-Floyd 算法

floyd算法 是动态规划的思想吗

a*算法求最短路径和floyd还有dijsktra算法求最短路径的区别?

最短路(Floyd算法的动态规划本质)- HDU 2544