1,核心思路:
通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。
其状态转移方程:map[i,j]=min{map[i,k]+map[k,j],map[i.j]} map[i,j]表示i到j的最短距离,k是穷举i,j的断点。
2,算法流程:
1,把图用邻接矩阵G表示出来,如果从Vi 到Vj 有路可达,则G[i,j]=d,d表示该路的长度,否则G[i,j]=最大值。
2,遍历这个矩阵,G[i,j]=min(G[i,j],G[i,k]+G[k,j]);
3,核心代码:
for(k=1;k<=n;k++) { for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(G[i,j]>G[i,k]+G[k,j]) G[i,j]=G[i,k]+G[k,j]; } } }
4,优缺点:
优点:Floyd 算法适用于稠密图,简单有效,容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据。
5,
时间复杂度:O(n^3)
空间复杂度:O(n^2)
举例一个练习题目:http://acm.hdu.edu.cn/showproblem.php?pid=1690
这个题目最关键的地方就是构图,因为数据较小,所以O(n^3)不会超时。构图的时候比较麻烦,没有什么大的技术含量,贴一下代码。
#include<stdio.h> #define INF 100000000000 #define MAXN 150 __int64 L[5],C[5]; __int64 map[MAXN][MAXN],X[MAXN]; int n,m; void Input_Deal() { int i,j; for(i=1;i<=4;i++) scanf("%I64d",&L[i]); for(i=1;i<=4;i++) scanf("%I64d",&C[i]); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%I64d",&X[i]);//输入部分 for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(i==j) map[i][j]=0; else map[i][j]=INF; } for(i=1;i<=n;i++) { map[i][i]=0; for(j=i+1;j<=n;j++) { __int64 distance=X[j]-X[i]; if(distance<0) distance=-distance; if(distance>L[4]) map[i][j]=map[j][i]=INF; else if(distance>L[3]) map[i][j]=map[j][i]=C[4]; else if(distance>L[2]) map[i][j]=map[j][i]=C[3]; else if(distance>L[1]) map[i][j]=map[j][i]=C[2]; else if(distance>0) map[i][j]=map[j][i]=C[1]; }//构图部分 } } void Floyd(int n) { int i,j,k; for(k=1;k<=n;k++){ for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(map[i][j]>map[i][k]+map[k][j]) map[i][j]=map[i][k]+map[k][j]; } } }//利用floyd找最少花费 } int main() { int t,ca=1,i; scanf("%d",&t); while(t--) { Input_Deal(); Floyd(n); printf("Case %d:/n",ca++); for(i=1;i<=m;i++) { __int64 start,aim; scanf("%I64d%I64d",&start,&aim); if(map[start][aim]==INF) { printf("Station %I64d and station %I64d are not attainable./n",start,aim); } else printf("The minimum cost between station %I64d and station %I64d is %I64d./n",start,aim,map[start][aim]); } } return 0; }