题目描述Description
假设有两条地铁线路,1 号线为直线线路,2 号线为环线线路,
假设 1 号线的各个站点名称分别为 “A” “B” “C” “D” “E”“F” “G” “H”
2号线的各个站点名称分别为"C" “I” “J” “K” “F” “L” “M” “N”;
另外,假设地铁都是双向运行的。 现给出两个地铁站名分别作为起点和终点,请给出从起点到终点至少需要多少站。
假如各个地铁站之间的距离不是相等的,相邻地铁站之间的距离保存在另
外一个数组中,应如何计算两个地铁站之间的最近距离。
在BFS算法之地铁路线问题一文中我们仅仅解决了两站点间经过最少站点的走法,但放眼现实生活,我们选择地铁线路的时候中间站点数量不是选择唯一的标准,某些时候我们想知道任意两站点间怎样走距离是最近的。
Floyd算法
求两个站点之间的最短距离问题可以转化为求解图中任意两点的最短距离,对于这类问题使用 Floyd算法 是可行的。
对于 Graph 矩阵:
i == j 时: Graph[i][j] == 0 站点距离为0
例: A站到A站距离为0
Graph[i][j] == ∞ 表示站 i 不可直接到达 j
j 不是 i 的直接后继
实现代码(含注释)
头文件
#pragma once
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
static int sstation;//起始站点
static int estation;//终止站点
struct route {//表示路线,即图中的每条边
int startSta;//起始站点编号
int endSta;//可以直接到达的下一站站点编号
int distance;//站点间距离
route(int s, int e, int d = 0) :startSta(s), endSta(e), distance(d) {}//构造函数
};
class SubwayRoute {
friend int main();//声明主函数为友元函数
int stationNums = 0;//站点数目
int minDis = 0;//记录最小距离
vector<string> staName;//各站点名
unordered_map<string, int> staNo;//每个站点对应的编号 如 A -> 0 的映射关系
//staInf 数组,站点可直接到达值则为站点间距离,否则值为0
vector<vector<int>> staInf;//邻接矩阵法存储站点间的信息:是否可以直接到达以及站点间距离
void init_staInf(vector<string>& stations, vector<route>& stas);//初始化站点信息
void printRouteInf();//打印邻接矩阵
void floydAlgorithm();//floyd算法求解任意两点间的最短路径
void printMinRoute(int u, int v, vector<vector<int>>& Path);//打印最短路径
};
源文件
#include "地铁路线问题(含有路线距离).h"
void SubwayRoute::init_staInf(vector<string>& stations, vector<route>& stas) {
stationNums = stations.size();//初始化站点数量
staName = stations;//站点信息初始化 各站点对应编号以及名称
int no = 0;
for (auto& sta : stations) {
staNo[sta] = no++;//哈希表记录各站点对应的编号
}
vector<vector<int>> tmp(stationNums, vector<int>(stationNums, 0));
staInf = tmp;
for (route& r : stas) {
staInf[r.startSta][r.endSta] = staInf[r.endSta][r.startSta] = r.distance;
}
}
void SubwayRoute::printRouteInf() {
cout << "邻接矩阵"<< endl <<"● 表示两站点直接连通 ○ 表示站点间不能直接到达" << endl<< " ";
for (int i = 0; i < stationNums; i++) {
cout << staName[i] << " ";
}cout << endl ;
for (int i = 0; i < stationNums; i++) {
cout << staName[i] << " ";
for (int j = 0; j < stationNums; j++) {
if (staInf[i][j]) cout << "●";
else cout << "○";
}cout << endl;
}
}
void SubwayRoute::floydAlgorithm() {
vector<vector<int>> Graph(stationNums, vector<int>(stationNums));//创建floyd算法矩阵
vector<vector<int>> Path(stationNums, vector<int>(stationNums, -1));//path数组初始化
//根据 staInf 站点距离信息矩阵填充Graph数组,为0的部分改为INT_MAX,其余不变
for (int i = 0; i < stationNums; i++) {
for (int j = 0; j < stationNums; j++) {
if (i == j) {
Graph[i][j] = 0;
}
else if (staInf[i][j] > 0) {
Graph[i][j] = staInf[i][j];
}
else if(staInf[i][j] == 0)
Graph[i][j] = INT_MAX / 2;//初始设置为无穷大 表示两点间不能直接到达
}
}
for (int v = 0; v < stationNums; v++) {
for (int i = 0; i < stationNums; i++) {
for (int j = 0; j < stationNums; j++) {
if (Graph[i][j] > Graph[v][j] + Graph[i][v]) {
Graph[i][j] = Graph[v][j] + Graph[i][v];
Path[i][j] = v;
}
}
}
}
printMinRoute(sstation, estation, Path);//打印路径
cout << "路径长度为 " << minDis;
}
//
void SubwayRoute::printMinRoute(int u, int v, vector<vector<int>>& Path) {
if (Path[u][v] == -1) {
minDis += staInf[u][v];//记录路径距离
cout << staName[u] << "->" << staName[v] << "距离为:" << staInf[u][v] << endl;
}
else {
int mid = Path[u][v];
printMinRoute(u, mid, Path);
printMinRoute(mid, v, Path);
}
}
int main() {
//各站点名
vector<string> stations{ "A","B","C","D","E","F","G","H","I","J","K","L","M","N" };
//各站点信息 使用结构体 route 表示
vector<route> stas{ route(0,1,2),route(1,2,4),route(2,8,7),route(2,13,8),
route(2,3,5),route(3,4,11),route(4,5,6),route(5,6,3),
route(6,7,1),route(8,9,5),route(9,10,8),route(10,5,4),route(13,12,6),route(12,11,7),route(11,5,10) };
//创建类对象
SubwayRoute sr;
//传入 stations 以及 stas 初始化对象属性
sr.init_staInf(stations, stas);
//打印邻接矩阵
sr.printRouteInf();
//字符串保存输入的站点名并判断站点是否合法
string sta("");
cout << "请输入起始站: (A ~ E)" << endl;
cin >> sta;
while (sr.staNo.find(sta) == sr.staNo.end()) {
cout << "无此站点,请重新输入!" << endl;
cin >> sta;
}
sstation = sr.staNo[sta];
cout << "请输入终点站:(A ~ E)" << endl;
cin >> sta;
while (sr.staNo.find(sta) == sr.staNo.end()) {
cout << "无此站点,请重新输入!" << endl;
cin >> sta;
}
estation = sr.staNo[sta];
sr.floydAlgorithm();//调用弗洛伊德求解 sstation 到 estation 的最短路径
return 0;
}
运行图