最短路径算法 ——求出路径长度 (*^__^*) 嘻嘻……

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 } 

 

以上是关于最短路径算法 ——求出路径长度 (*^__^*) 嘻嘻……的主要内容,如果未能解决你的问题,请参考以下文章

最短路径算法之Dijkstra算法

求最短路径长度--简单易懂

图 - 最短路径 (二)

有向图单源非负权值回路最短路径——BellmanFord算法

【数据结构】最短路径之迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法

dijkstra算法怎么记录路径