参考了这位大神的思路。http://blog.csdn.net/bendaai/article/details/63253277
注释了下代码,方便看了。PS:这个题想了好久好久好久好久。。感觉自己太弱了。
再处理地铁地图的时候最开始用一个数组标记地铁线的,然后标记出换乘车站,把问题复杂化了。
我们建一个这样的图,以地铁站的号为标记,这个节点里面存储相连的车站和线号。看下面这个图。原图引用自:https://www.patest.cn/contests/pat-a-practise/1131
这样有什么好处呢?
这样可以很容易的处理线号,不至于说像我之前那样区别处理要分很多情况。然后用DFS+回溯的方法,遍历图。
#include <iostream>
#include <vector>
#include <cstring>
#define MAX 10010
using namespace std;
struct Station {//车站节点 包括车站号和线号
int No;
int LineNo;
Station(int no, int lineno) {
No = no;
LineNo = lineno;
}
};
struct MapNode { //地铁网线图 包含相连车站的车站号和线号
vector <Station> Link;
};
struct Segment { //乘车区间
int LineNo;
int Start, End;
Segment(int lineno, int st, int ed) {
LineNo = lineno;
Start = st;
End = ed;
}
};
struct Ans {//最后结果
vector <Segment> list;//所有乘车区间
int len;//所需长度
bool operator<(const Ans a2) const {
if (len != a2.len)
return len < a2.len;
else
return list.size() < a2.list.size();
}
};
MapNode SubMap[MAX];
int n, m, k;
bool isVis[MAX];
Ans ThisAns;
Ans FinalAns;
void DFS(int u, int ed) { //u当前访问节点
if (u == ed) {//已经遍历完成
if (ThisAns < FinalAns)//当前结果更优
FinalAns = ThisAns;
}
//当前结果已经不如目前最优结果 不再继续遍历
if (FinalAns < ThisAns)
return;
for (int i = 0; i < SubMap[u].Link.size(); i++) { //访问u的相连站
int v = SubMap[u].Link[i].No;
if (!isVis[v]) {//v没有访问过
Ans TempAns = ThisAns;//保存当前结果 方便后面回溯
ThisAns.len++;
if (SubMap[u].Link[i].LineNo != ThisAns.list.back().LineNo)
ThisAns.list.push_back(Segment(SubMap[u].Link[i].LineNo, u, v));
else
ThisAns.list.back().End = v;
isVis[v] = true;
DFS(v, ed);
//回溯
isVis[v] = false;
ThisAns = TempAns;
}
}
}
void ParamInit() {//初始化参数
memset(isVis, false, sizeof(isVis));
ThisAns.list.clear();
ThisAns.len = 0;
ThisAns.list.push_back(Segment(-1, -1, -1));//添加一个初始节点 方便后面的判断
FinalAns.list.clear();
FinalAns.len = MAX;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> m;
int PreNo, StaNo;
cin >> PreNo;
for (int j = 1; j < m; j++) {
cin >> StaNo;
SubMap[PreNo].Link.push_back(Station(StaNo, i));
SubMap[StaNo].Link.push_back(Station(PreNo, i));
PreNo = StaNo;
}
}
cin >> k;
for (int i = 0; i < k; i++) {
ParamInit();//初始化参数
int st, ed;
cin >> st >> ed;
DFS(st, ed);
cout << FinalAns.len << endl;
for (int i = 1; i < FinalAns.list.size(); i++) {
printf("Take Line#%d from %04d to %04d.\n", FinalAns.list[i].LineNo, FinalAns.list[i].Start, FinalAns.list[i].End);
}
}
return 0;
}