您的位置:首页 > 其它

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

2017-04-02 11:39 155 查看
题目大致就是找到一个图的最短路径,没什么新意,不过关键是!关键是!我没写出来……

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

对于这种无负边的最短路径可以用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] << "\t";
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] << "\t";
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
结果如下

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: