地铁换乘——华为2014校招机试样题
——方法一:Dijkstra最短路径算法
原题如下:
地铁换乘
描述:
已知2条地铁线路,其中A为环线,B为东西向线路,线路都是双向的。经过的站点名分别如下,两条线交叉的换乘点用T1、T2表示。编写程序,任意输入两个站点名称,输出乘坐地铁最少需要经过的车站数量(含输入的起点和终点,换乘站点只计算一次)。
地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10A11 A12 A13 T2 A14 A15 A16 A17 A18
地铁线B(直线)经过车站:B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B10T2 B11 B12 B13 B14 B15
运行时间限制: 无限制
内存限制: 无限制
输入: 输入两个不同的站名
输出: 输出最少经过的站数,含输入的起点和终点,换乘站点只计算一次
样例输入: A1 A3
样例输出: 3
上星期试着解这道题,当时还没看数据结构图的部分,想着用双链表加上各种条件判断来解决,发现太复杂了,遂网上搜了搜,这里提供了一种通过图来解决的Floyed算法,链接如下:
http://blog.csdn.net/arcsinsin/article/details/11267755
鉴于此,这几天赶紧去看了下图的部分,刚看了Dijkstra单源点到所有终点的最短路径算法,想来可以改造下解决这里的问题,遂解决如下。
关于Dijkstra算法可以参见这里:
http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html
#include <iostream>
#include <string>
#include <stack>
using namespace std;
#define SIZE_A 21
#define SIZE_B 17
#define N 35
// 20 + 1
string A[] = {"A1","A2","A3","A4","A5","A6","A7","A8","A9","T1","A10","A11","A12","A13","T2","A14","A15","A16","A17","A18","A1"};
// 17
string B[] = {"B1","B2","B3","B4","B5","T1","B6","B7","B8","B9","B10","T2","B11","B12","B13","B14","B15"};
// 35
string Node[] = {"A1","A2","A3","A4","A5","A6","A7","A8","A9","T1","A10","A11","A12","A13","T2","A14","A15","A16","A17","A18",
"B1","B2","B3","B4","B5","B6","B7","B8","B9","B10","B11","B12","B13","B14","B15"};
struct Graph {
int matrix[N][N];
int n;
int e;
};
Graph g;
bool s[N];
int dist[N];
int path[N];
int length=0;
string StrBegin,StrEnd;
void Dijkstra(int v0, int v1);
int GetPos(string *array, string & str)
{
int n=0;
if (str[0] == 'B') {
n+=20;
array+=20;
}
if (str == "T1") return 9;
if (str == "T2") return 14;
while (*array != str) {
array ++;
n++;
}
return n;
}
void BuildGraph()
{
// 初始化matrix
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
g.matrix[i][j]=0;
}
}
// 根据A建立边信息
for (int i=0; i<(SIZE_A-1); i++)
{
int u = GetPos(Node,A[i]);
int v = GetPos(Node,A[i+1]);
g.matrix[u][v]=1;
g.matrix[v][u]=1;
}
// 根据B建立边信息
for (int i=0; i<(SIZE_B-1); i++)
{
int u = GetPos(Node,B[i]);
int v = GetPos(Node,B[i+1]);
g.matrix[u][v]=1;
g.matrix[v][u]=1;
}
int u = GetPos(Node,StrBegin);
int v = GetPos(Node,StrEnd);
Dijkstra(u,v);
}
void Dijkstra(int v0, int v1)
{
// 1、初始化
for (int i=0; i<N; i++)
{
s[i] = false;
if (g.matrix[v0][i] != 0)
{
dist[i] = g.matrix[v0][i];
path[i] = v0;
}
else
{
dist[i] = INT_MAX;
path[i] = -1;
}
}
s[v0]=true;
dist[v0]=0;
path[v0]=v0;
// 2、循环n-1次
for (int i=0; i<(N-1); i++)
{
// 2.1、取dist[u]最小的u
int min=INT_MAX;
int u;
for (int j=0; j<N; j++)
{
if (s[j] == false && dist[j] < min)
{
min = dist[j];
u = j;
}
}
s[u] = true;
// 2.2、更新u邻接的所有w
for (int w=0; w<N; w++)
{
if (s[w] == false && g.matrix[u][w] != 0)
{
if (dist[u] + g.matrix[u][w] < dist[w])
{
dist[w] = dist[u] + g.matrix[u][w];
path[w] = u;
}
}
}
}
// 3、获取结果
while (v1 != v0)
{
v1 = path[v1];
length++;
}
length ++;
//stack<int> s;
//while (v1 != v0)
//{
// s.push(v1);
// v1 = path[v1];
//}
//s.push(v0);
//while (!s.empty())
//{
// length++;
// if (1) // debug
// {
// int pos = s.top();
// string str = Node[pos];
// str += "\0";
// cout<<str<<" ";
// }
// s.pop();
//}
}
int main()
{
//while(0)
{
length = 0;
cin>>StrBegin>>StrEnd;
if (StrBegin == StrEnd)
cout<<"1"<<endl;
else
{
BuildGraph();
cout<<length<<endl;
}
system("pause");
}
return 0;
}
——方法二:Floyd-Warshall顶点对最短路径算法
该算法可以求出各顶点对之间的最短路径,写法简单,主要核心就是一个三层嵌套循环即可。
#include <iostream>
#include <string>
#include <stack>
using namespace std;
#define SIZE_A 21
#define SIZE_B 17
#define N 35
#define INF 0xfffff
// 20 + 1
string A[] = {"A1","A2","A3","A4","A5","A6","A7","A8","A9","T1","A10","A11","A12","A13","T2","A14","A15","A16","A17","A18","A1"};
// 17
string B[] = {"B1","B2","B3","B4","B5","T1","B6","B7","B8","B9","B10","T2","B11","B12","B13","B14","B15"};
// 35
string Node[] = {"A1","A2","A3","A4","A5","A6","A7","A8","A9","T1","A10","A11","A12","A13","T2","A14","A15","A16","A17","A18",
"B1","B2","B3","B4","B5","B6","B7","B8","B9","B10","B11","B12","B13","B14","B15"};
int matrix[N][N];
int dist[N][N];
int path[N][N];
int length=0;
string StrBegin,StrEnd;
void Floyd_Warshall();
int GetPos(string *array, string & str)
{
int n=0;
if (str[0] == 'B') {
n+=20;
array+=20;
}
if (str == "T1") return 9;
if (str == "T2") return 14;
while (*array != str) {
array ++;
n++;
}
return n;
}
void BuildGraph()
{
// 初始化matrix
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
matrix[i][j]=0;
}
}
// 根据A建立边信息
for (int i=0; i<(SIZE_A-1); i++)
{
int u = GetPos(Node,A[i]);
int v = GetPos(Node,A[i+1]);
matrix[u][v]=1;
matrix[v][u]=1;
}
// 根据B建立边信息
for (int i=0; i<(SIZE_B-1); i++)
{
int u = GetPos(Node,B[i]);
int v = GetPos(Node,B[i+1]);
matrix[u][v]=1;
matrix[v][u]=1;
}
int u = GetPos(Node,StrBegin);
int v = GetPos(Node,StrEnd);
Floyd_Warshall();
}
void Floyd_Warshall()
{
// 1、初始化
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
if( i != j && matrix[i][j] > 0)
{
dist[i][j] = matrix[i][j];
path[i][j] = i;
}
else
{
dist[i][j] = INF;
path[i][j] = -1;
}
}
}
// 2、Floyd核心三层循环
for (int k=0; k<N; k++)
{
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
if (dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = path[k][j];
}
}
}
}
// 3、输出结果
int u = GetPos(Node,StrBegin);
int v = GetPos(Node,StrEnd);
while (u != v)
{
v = path[u][v];
length++;
}
length ++;
}
int main()
{
//while(0)
{
length = 0;
cin>>StrBegin>>StrEnd;
if (StrBegin == StrEnd)
cout<<"1"<<endl;
else
{
BuildGraph();
cout<<length<<endl;
}
system("pause");
}
return 0;
}