Metro
Metro
需求分析
实际已包含于题目中。
大致包括:地铁线路展示,提供各个地铁站之间的最佳换乘路线。
存储和后端的实现难度预估小于前端的实现。
后端设计思路
题目所给定的地铁辅助规划在实际应用上是意见非常困难的事,当然我们在编写代码时会自动忽略这些(笑),而将地铁网简单地缩略为一张**无向图**。这样一来题目所要求的最短路径规划问题就变成了最基本的**最短路**问题。
作为单源最短路问题,我们首先需要建图; 北京的地铁路线图实际上只包含两个环线和18条一半路线,所以我们可以直接构造一半路线和环线的邻接矩阵,最后手动输入54个换乘站点的信息。
由于我的数据存储形式为每条路线单独存储,所以换乘站点会出现在数条线路中,我们只需要把相同的站点的距离权值设置为0,并把普通的相邻站点距离权值设置为1即可解决图的创建。
通过$ Dijkstra $ 计算最短路时可以同时保存路径。最后输出路径时再暴力枚举是否存在换乘情况即可。
## 前端显示
本来想利用html5来进行网页的显示,最后由于前端技术太差(哭)改用丑陋的命令行...
具体的显示效果可以参照实际测试结果
理论复杂度
运算时间处理:$ \mathcal{O}(N^2) $
理论空间消耗 $ \mathcal{O}(N^2) <= 10Mb $
代码部分
负责计算单元最短路的函数
void CAL() //Dijkstra
{
dis[st] = 0;
for (int i = 1 ; i <= MAXN ; i ++ ) {
int minv = INF;
int u = -1;
for (int j = 1 ; j <= MAXN ; j ++) {
if (dis[j] < minv && vis[j] == 0) {
minv = dis[j];
u = j;
}
}
if (u == -1)
return;
vis[u] = 1;
for (int v = 1 ; v <= MAXN ; v ++) {
if (vis[v]==0 && G[u][v]!=INF) {
if (dis[v] > dis[u]+G[u][v])
dis[v] = dis[u]+G[u][v];
ANS[v] = u;
}
}
}
}
PRINT();
}
**输出函数** ``` void PRINT() { int r,ss = en,k = 0; cout << "\n *** 查询结果 ***\n" << "路线共" << dis[en]+1 << "站:\n";
while (ANS[en] != -1) {
k++;
RES[k] = en;
// cout << en << " ";
en = ANS[en];
}
int RESS[151],RESROUTE[151];
for (int i = k ; i >= 1 ; i --) // Reserve and Add
RESS[k-i+2] = RES[i];
RESS[1] = st;
RESS[k+1] = ss;
k ++;
for (int i = 1 ; i <= k ; i ++) {
int p = 1;
while (!(RESS[i] > Pre[p] && RESS[i] <= Pre[p+1]))
p ++;
RESROUTE[i] = p;
}
int o = RESROUTE[1];
int z = 1;
cout << "< " << ROUTEI[o] << " > :";
bool F = false;
while (z <= k) {
while (RESROUTE[z] == o) {
cout << " " << SPOTI[RESROUTE[z]][RESS[z] - Pre[RESROUTE[z]]];
z ++;
if (z > k) {
F = true;
break;
}
}
if (F)
break;
if (RESROUTE[z] != o) {
o = RESROUTE[z];
cout << "\n< " << ROUTEI[o] << " > :";
}
z ++;
}
// Clear
strt = st = stt = enrt = en = enn = 0;
for (int i = 0 ; i < MAXN ; i ++) {
ANS[i] = -1;
dis[i] = INF;
}
memset(vis,0,sizeof(vis));
cout << '\n';
}
</br>
**建图部分**
for (int i = 1 ; i <= MAXN ; i ++) //Init
for (int j = 1 ; j <= MAXN ; j ++)
G[i][j] = INF; //普通线性线路
for (int i = 1 ; i <= 20 ; i ++)
for (int j = 1 ; j < CNT[i] ; j ++) {
G[Pre[i]+j][Pre[i]+j+1] = 1;
G[Pre[i]+j+1][Pre[i]+j] = 1;
}
//环形相连
G[Pre[2]+1][Pre[2]+CNT[2]] = 1;
G[Pre[2]+CNT[2]][Pre[2]+1] = 1;
G[Pre[10]+1][Pre[10]+CNT[10]] = 1;
G[Pre[10]+CNT[10]][Pre[10]+1] = 1;
//换乘相连
for (int i = 1 ; i <= EX ; i ++) {
G[EXCHANGE[i][0]][EXCHANGE[i][1]] = 0;
G[EXCHANGE[i][1]][EXCHANGE[i][0]] = 0;
if (EXCHANGE[i][2] != -1) {
G[EXCHANGE[i][0]][EXCHANGE[i][2]] = 0;
G[EXCHANGE[i][2]][EXCHANGE[i][0]] = 0;
G[EXCHANGE[i][1]][EXCHANGE[i][2]] = 0;
G[EXCHANGE[i][2]][EXCHANGE[i][1]] = 0;
}
}
</br>
## 实际测试结果
</br>
**最短路查询 **
![a](https://img2018.cnblogs.com/blog/1806376/201910/1806376-20191013184125868-493002372.png)
</br>
**路线图查询**
![avatar](https://img2018.cnblogs.com/blog/1806376/201910/1806376-20191013183822374-110625714.png)
</br>
**异常处理**
站点信息为内置并且采用了用户参照选择的方式而非直接站点输入的方式。
具体情况有以下两种:
***无效站点参数!***
***无效路线参数!***
请自行测试