最短路径算法 ——求出路径长度 (*^__^*) 嘻嘻……
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路径算法 ——求出路径长度 (*^__^*) 嘻嘻……相关的知识,希望对你有一定的参考价值。
【问题描述】:
平面上有n(n<=100)个点,每个点的坐标均在-10000~10000之间。
其中的一些点之间有连线。若有连线,则表示可以从一个点到达另一个点,即两点之间有通路,通路的距离为两点之间的直线距离。
现在的任务是找出从一个点到另一个点的最短路径。
【输入格式】:
第1行:整数n
第2行到第n+1:每行两个整数x y,描述了一个点的坐标。
第n+2行:一个整数m,表示图中连线的个数
此后m行:每行描述一条连线,由两个整数i和j构成,表示第i个点和第j个点之间有连线
最后一行:两个整数s t,分别表示源点和目标点
【输出格式】:
仅一行,一个实数(保留两位小数),表示从s到t的最短路径长度
【输入样例】:
5
0 0
2 0
2 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
【输出样例】:
3.41
1.Floyed-Warshall 算法 O(N^3)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 int a[101][3]; 7 double f[101][101]; 8 int n,m,x,y,s,e,k; 9 int maxx=0X7f; 10 int main() 11 { 12 int i,j; 13 scanf("%d",&n); 14 for(i=1;i<=n;i++) 15 { 16 cin>>a[i][1]>>a[i][2]; 17 } 18 scanf("%d",&m); 19 memset(f,maxx,sizeof(f)); 20 for(i=1;i<=m;i++) 21 { 22 cin>>x>>y; 23 f[x][y]=f[y][x]=sqrt(pow(double(a[x][1]-a[y][1]),2)+pow(double(a[x][2]-a[y][2]),2)); 24 } 25 scanf("%d%d",&s,&e); 26 27 /*最外层的k是枚举位于起点和终点中的跳板,贪心的正确性必须得到保证, 28 而这个保证在于,再求f[i][j]时,f[i][k]和f[k][j]若可达(一般来说把不可达设置为无穷大), 29 必须为最优值(即最短距离).其中k作为中间点,我们是把它当作阶段,而起点,终点的i,j我们称为状态(参考动态规划)—— 30 第k次循环后,保证每个点到顶点k的距离,要么不可达,要么是最短距离,大前提是距离上除了起点和终点只有1~k-1这k-1个点。 31 当我们的k值从1枚举到n(假设顶点下标从1开始编号),那么我们获得的最短路径上允许出现的点的编号,就从1增加到n,当n被允许加入路径中, 32 那么这个最短路径问题就得到解决。因为所有的顶点在最短路径的位置都被考虑了。*/ 33 34 for(k=1;k<=n;k++) 35 for(i=1;i<=n;i++) 36 for(j=1;j<=n;j++) 37 if((i!=j)&&(i!=k)&&(j!=k) &&f[i][k]+f[k][j]<f[i][j]) 38 f[i][j]=f[i][k]+f[k][j]; 39 printf("%.2lf",f[s][e]); 40 return 0; 41 }
2.Dijkstrs 算法 O(N^2)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 bool b[101]; 7 double f[101][101]; 8 int a[101][3]; 9 double c[101]; 10 double maxx=1e30; 11 int main() 12 { 13 int i,n,j,k,x,y,s,e,m; 14 cin>>n; 15 for(i=1;i<=n;i++)//读入n个点的坐标 16 cin>>a[i][1]>>a[i][2]; 17 18 for(i=1;i<=n;i++)//f数组初始值最大化 19 for(j=1;j<=n;j++) 20 f[i][j]=maxx; 21 cin>>m; 22 for(i=1;i<=m;i++) 23 { 24 cin>>x>>y; 25 f[x][y]=f[y][x]=sqrt(pow(a[x][1]-a[y][1],2)+pow(a[x][2]-a[y][2],2));//求两个点间的距离(两点间的坐标距离公式) 26 27 } 28 cin>>s>>e; 29 30 for(i=1;i<=n;i++)//每个点到起点的最短路径最开始赋值为与起点的坐标距离 31 c[i]=f[s][i]; 32 33 b[s]=true; 34 c[s]=0; 35 for(i=1;i<=n-1;i++)//查找可以更新的节点 36 { 37 double minil=maxx; 38 k=0; 39 for(j=1;j<=n;j++) //在没有被访问过的点中,找一点k使得才c[k]值最小 40 if((!b[j]) && c[j]<minil) 41 { 42 minil=c[j]; 43 k=j; 44 } 45 if(k==0) break;//所有的点都被访问就退出循环 46 47 b[k]=true; //把点k标记为已确定的最短路径 48 49 for(j=1;j<=n;j++) //对与k相连的点的最短路径进行更新 50 if(c[k]+f[k][j]<c[j]) 51 c[j]=c[k]+f[k][j]; 52 53 } 54 printf("%.2f\n",c[e]); 55 return 0; 56 57 58 }
3.Bellman-Ford 算法 O(NE) //福特算法
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 int a[101][3]; 7 double dis[1001],w[1001]; 8 int f[103][3]; 9 int maxx=0X7fffffff/3; 10 int main() 11 { 12 int s,t,i,j,k,n,m,x,y; 13 cin>>n; 14 for(i=1;i<=n;i++) 15 scanf("%d%d",&a[i][1],&a[i][2]); 16 cin>>m; 17 for(i=1;i<=m;i++) 18 { 19 dis[i]=maxx; 20 f[i][1]=f[i][2]=maxx; 21 } 22 for(i=1;i<=m;i++) 23 { 24 scanf("%d%d",&x,&y); 25 f[i][1]=x; 26 f[i][2]=y; 27 w[i]=sqrt(pow(a[x][1]-a[y][1],2)+pow(a[x][2]-a[y][2],2)); 28 29 } 30 cin>>s>>t; 31 dis[s]=0; 32 for(i=1;i<=n;i++) 33 for(j=1;j<=m;j++) 34 { 35 if(dis[f[j][1]]+w[j]<dis[f[j][2]]) dis[f[j][2]]=dis[f[j][1]]+w[j]; 36 if(dis[f[j][2]]+w[j]<dis[f[j][1]]) dis[f[j][1]]=dis[f[j][2]]+w[j]; 37 } 38 printf("%.2f",dis[t]); 39 return 0; 40 41 }
以上是关于最短路径算法 ——求出路径长度 (*^__^*) 嘻嘻……的主要内容,如果未能解决你的问题,请参考以下文章
有向图单源非负权值回路最短路径——BellmanFord算法