Dijkstra最短路径——2017华为实习在线机试

题目大致就是找到一个图的最短路径,没什么新意,不过关键是!关键是!我没写出来……

上上篇文章——图的所有路径输出可以解决,不过要计算所有路径,工作量比较大,可能是超时。

对于这种无负边的最短路径可以用Dijkstra求解。

代码注释很全,可以直接看懂:

  1 #include <iostream>
  2 #include <fstream>
  3 #include <vector>
  4 #include <algorithm>
  5 #include <string>
  6 #include <list>
  7 #include <stack>
  8 #include <queue>
  9 
 10 using namespace std;
 11 
 12 typedef struct point{
 13     int x;
 14     int y;
 15     point *previous;
 16     int step;
 17 } point;
 18 
 19 /*
 20 int map[6][6] = {
 21     { 0, 2, 10, 5, 3, -1 },
 22     { -1, 0, 12, -1, -1, 10 },
 23     { -1, -1, 0, -1, 7, -1 },
 24     { 2, -1, -1, 0, 2, -1 },
 25     { 4, -1, -1, 1, 0, -1 },
 26     { 3, -1, 1, -1, 2, 0 }
 27 };*/
 28 int map[6][6] = {
 29     { -1, 2, 10, -1, 3, -1 },
 30     { -1, -1, 12, -1, -1, 10 },
 31     { -1, -1, -1, -1, 7, -1 },
 32     { -1, -1, -1, -1, -1, -1 },
 33     { 4, -1, -1, -1, -1, -1 },
 34     { 3, -1, 1, -1, 2, -1 }
 35 };
 36 /*
 37 int map[6][6] = {
 38     {-1,-1,10,-1,30,100},
 39     {-1,-1,5,-1,-1,-1},
 40     {-1,-1,-1,50,-1,-1},
 41     {-1,-1,-1,-1,-1,10},
 42     {-1,-1,-1,20,-1,60},
 43     {-1,-1,-1,-1,-1,-1},
 44 };*/
 45 /*
 46 int map[6][6] = {
 47     { -1, -1, 10, -1, 30, 100 },
 48     { -1, -1, 5, -1, -1, -1 },
 49     { -1, -1, -1, 50, -1, -1 },
 50     { -1, -1, -1, -1, -1, 10 },
 51     { -1, -1, -1, 20, -1, 60 },
 52     { -1, -1, -1, -1, -1, -1 },
 53 };*/
 54 
 55 void PrintMostShortPath(vector<int> path, vector<int> D, int startPoint, int endPoint)
 56 {
 57     int s = endPoint;
 58     vector<int> v;
 59     v.push_back(endPoint);
 60 
 61     while (path[s] != startPoint)
 62     {
 63         v.push_back(path[s]);
 64         s = path[s];
 65     }
 66     v.push_back(startPoint);
 67 
 68     cout << "最短路径为:";
 69     for (int i = v.size() - 1; i >= 0; i--)
 70     {
 71         cout << " " << v[i];
 72     }
 73     cout << endl;
 74     cout << "最距离为为:" << D[endPoint] << endl;
 75 }
 76 
 77 void PrintIntVector(vector<int> v)
 78 {
 79     for (int i = 0; i < v.size(); i++)
 80     {
 81         cout << v[i] << "	";
 82     }
 83     cout << endl;
 84 }
 85 void PrintBoolVector(vector<bool> v)
 86 {
 87     for (int i = 0; i < v.size(); i++)
 88     {
 89         cout << v[i] << "	";
 90     }
 91     cout << endl;
 92 }
 93 
 94 //算法对于负边图无效
 95 void Dijkstra(int startPoint,int endPoint)
 96 {
 97     //获取图边长
 98     int n = 6;
 99 
100     //初始化变量
101     vector<bool> S(n);//标记节点是否走过
102     vector<int> D(n);//从起点到该点的最短距离
103     vector<int> Path(n);//该点的前驱节点
104     int v = 0;
105     int min = 0;
106 
107     //初始化变量
108     for (int i = 0; i < n; i++)
109     {
110         S[i] = false;
111         D[i] = map[startPoint][i];
112         //有边
113         if (D[i] >0)
114         {
115             Path[i] = startPoint;
116         }
117         else
118         {
119             Path[i] = -1;
120         }
121     }
122     S[startPoint] = true;
123     D[startPoint] = 0;
124 
125     //初始化打印
126     cout << "已经走过的节点S:    "; PrintBoolVector(S);
127     cout << "当前最短路径D:        "; PrintIntVector(D);
128     cout << "前驱符号Path:        "; PrintIntVector(Path);
129 
130     //再循环n-1次,把剩下的n-1个节点都走一遍
131     for (int j = 1; j < n; j++)
132     {
133         min = 32767;
134         v = 0;
135 
136         //寻找当前最短路径D中,未走过并且,可以到达的,距离最短节点。
137         for (int i = 0; i < n; i++)
138         {
139             if (S[i] == false && D[i] != -1 && (D[i] < min))
140             {
141                 v = i;
142                 min = D[i];
143             }
144         }
145         S[v] = true;//v为中转节点,标记走过
146 
147         //以v为中转点走到i节点和现有到i路径比较
148         for (int i = 0; i < n; i++)
149         {
150             //这个||很关键。两种需要更新的情况。一种是通过中转小于目前的最短距离,另一种是直接可以到的(在map中有v到i的路径)
151             //第一个:没走过的点,第二个:能走的点,第三个:1.通过中转点走比直接走小2.在map中v-i可以走,但是在D中未更新的情况
152             //dijkstra关键有就是一个更新的操作
153             if (S[i] == false && map[v][i] != -1 && (D[v] + map[v][i] < D[i] || D[i] == -1))
154             {
155                 D[i] = D[v] + map[v][i];
156                 Path[i] = v;
157             }
158         }
159 
160         //打印每次的结果
161         cout << "" << j << "次:" << endl;
162         cout << "已经走过的节点S:    "; PrintBoolVector(S);
163         cout << "当前最短路径D:        "; PrintIntVector(D);
164         cout << "前驱符号Path:        "; PrintIntVector(Path);
165     }
166     PrintMostShortPath(Path, D, startPoint, endPoint);
167 }
168 
169 int main()
170 {
171     int startPoint = 4;
172     int endPoint = 1;
173 
174     Dijkstra(startPoint, endPoint);
175 
176     return 0;
177 }
View Code

结果如下

原文地址:https://www.cnblogs.com/wyc199288/p/6658641.html