算法分析与实践-作业2

最短路径

1. 问题

    用于计算一个节点到其他所有节点的最短路径。

2. 解析

    Floyd:

    1.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。

    2.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。

    把图用邻接矩阵dis表示出来,如果从Vi到Vj有路可达,则dis[i][j]=d,d表示该路的长度;否则dis[i][j]=无穷大。假设Vk是从Vi到Vj需要经过的点,把各个顶点插入图中,比较插点后的距离与原来的距离,dis[i][j] = min( dis[i][j], dis[i][k]+dis[k][j] ),如果dis[i][j]的值变小,则表明可以用Vk来更新Vi和Vj之间的距离。

    Dijkstra:

    从起始点开始,采用贪心的策略,每次遍历到距离始点距离最近且未被访问过的顶点的邻接节点,直到扩展到终点为止。

3. 设计

    Floyd:

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int inf= 0x3f3f3f3f;
 4 const int maxn= 100 + 10;
 5 int dis[maxn][maxn];
 6 int n,m;   //n表示顶点数量,m表示边的数量
 7 //----------以下为floyd算法----------// 
 8 void floyd(){
 9     for(int k=1;k<=n;++k){
10         for(int i=1;i<=n;++i){
11             for(int j=1;j<=n;++j){
12                 if(dis[i][k]+dis[k][j]<dis[i][j])
13                     dis[i][j]=dis[i][k]+dis[k][j];
14             }
15         }
16     } 
17 }
18 //----------以上为floyd算法----------// 
19 int main(){
20     while(scanf("%d %d",&n,&m)!=EOF){
21         memset(dis,inf,sizeof dis);      //初始化,令各个点之间的距离为无穷大 
22         for(int i=1;i<=m;++i){
23             int x,y,z;
24             scanf("%d %d %d",&x,&y,&z);
25             dis[x][y]=z;                //有向图 
26         }
27         for(int i=1;i<=n;++i)dis[i][i]=0;
28         floyd();
29         puts("以下为距离矩阵:"); 
30         for(int i=1;i<=n;++i){          //输出距离矩阵 
31             printf("%d: ",i);
32             for(int j=1;j<=n;++j){
33                 printf("%d%c",dis[i][j],j==n?'\n':' ');
34             }
35         }
36     }
37 } 

    Dijkstra:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 1010;
 6 const int inf = 0x3f3f3f3f;
 7 int mp[maxn][maxn];
 8 int dis[maxn];
 9 bool vis[maxn];
10 int n, m;                                             //n表示顶点数量,m表示边的数量 
11 //----------以下为dijkstra算法----------// 
12 void dijkstra(int s) {                                //从s点出发,经过任意点
13     memset(vis, false, sizeof(vis));
14     memset(dis, inf, sizeof(dis));
15     vis[s] = 1;                                       //判断该点是否被检查过
16     for (int i = 1; i <= n; i++){
17         dis[i] = mp[s][i];
18     }
19      dis[s] = 0; 
20     for (int time = 1; time <= n - 1; time++){         //共n个数,检查次数n-1次//
21         int minn = inf;
22         int p = 1;
23         for (int i = 1; i <= n; i++){                 //贪心 找出局部最优解
24             if (dis[i] < minn&&vis[i] != 1) {
25                 minn = dis[i];
26                 p = i;
27             }
28         }
29         vis[p] = 1;                                   //判断该点是否被检查过
30         for (int i = 1; i <= n; i++){                 //用p点优化所有点
31             dis[i] = min(dis[i], dis[p] + mp[p][i]);  //比较
32         }
33     }
34 }
35 //----------以上为dijkstra算法----------// 
36 int main(){
37     while(scanf("%d %d",&n,&m)!=EOF){
38         memset(mp,inf,sizeof mp);         //初始化,令各个点之间的距离为无穷大 
39         for(int i=1;i<=m;++i){
40             int x,y,z;
41             scanf("%d %d %d",&x,&y,&z);
42             mp[x][y]=z;                //有向图 
43         }
44         dijkstra(1);
45         printf("从1到n点的最短距离为:%d\n",dis[n]);
46     }
47 } 

4. 分析

    //n为点的数量

    flyod算法复杂度:O(n^3)

    dijkstra算法复杂度:O(n^2)

5. 源码

    Floyd: https://github.com/JayShao-Xie/algorithm-work/blob/master/floyd.cpp

    Dijkstra: https://github.com/JayShao-Xie/algorithm-work/blob/master/dijkstra.cpp

posted @ 2020-03-03 21:47  JayShao  阅读(131)  评论(0编辑  收藏  举报