PAT A1131 Subway Map
dfs,选择最优路径并输出~
这道题难度非常炸裂,要求完完整整自己推一遍,DFS才算过关!
思路:一遍dfs,过程中要维护两个变量,minCnt 中途停靠最少的站。minTransfer需要换成的最少次数
1 可以这样算出一条线路的换乘次数:在line数组里保存每两个相邻站中间的线路是几号线,从头到尾遍历最终保存的路径,preLine为前一小段线路编号,如果当前的节点和前一个节点组成的这条路的编号和preLine不同,说明有一个换乘,就将cnt+1,最后遍历完累加的cnt即是换乘的次数。
2 line数组的存储,用二维数组会内存超限,我们用unordered_map<int,int> line存储的方式,第一个int用来存储线路,每次将前四位存储在第一个线路,后四位存储在第二个线路,第二个int用来保存相邻的线路是几号线。
3 可以这样算出一条线路中途停站的次数,在dfs的时候有个变量cnt,表示当前路线是所需乘的第几个站,每次dfs的时候将cnt加一表示向下遍历一层,cnt就是当前中途停站的次数。
2 可以这样输出结果:和计算线路换乘次数思路一样,每当preLine和当前line值不同的时候就输出一句话,保存perTransfer表示上一个换乘站,最后不要忘记输出pretransfer和最后一个站之间的路,即使最后一个站不是换乘站。
#include<bits/stdc++.h> using namespace std; const int maxn=10010; unordered_map<int,int> line; vector<int> g[maxn]; vector<int> path,tmp; bool visit[maxn]={false}; int minCnt=1e9; int minTransferCnt=1e9; int st,ed; int transfer (vector<int> v) { int cnt=0,preLine=0; for (int i=1;i<v.size();i++) if (line[v[i-1]*10000+v[i]]!=preLine) { cnt++; preLine=line[v[i-1]*10000+v[i]]; } return cnt; } void dfs (int v) { visit[v]=true; tmp.push_back(v); if (v==ed) { int transferCnt=transfer(tmp); if (tmp.size()<minCnt) { minCnt=tmp.size(); minTransferCnt=transferCnt; path=tmp; } else if (tmp.size()==minCnt&&transferCnt<minTransferCnt) { minTransferCnt=transferCnt; path=tmp; } visit[v]=false; tmp.pop_back(); return; } for (int i=0;i<g[v].size();i++) { if (visit[g[v][i]]==false) { dfs (g[v][i]); } } visit[v]=false; tmp.pop_back(); } int main () { int N; scanf ("%d",&N); int k,pre,x; for (int i=1;i<=N;i++) { scanf ("%d %d",&k,&pre); for (int j=1;j<k;j++) { scanf ("%d",&x); g[pre].push_back(x); g[x].push_back(pre); line[pre*10000+x]=line[x*10000+pre]=i; pre=x; } } int q; scanf ("%d",&q); for (int i=0;i<q;i++) { scanf ("%d %d",&st,&ed); fill (visit,visit+maxn,false); minTransferCnt=1e9; minCnt=1e9; tmp.clear(); dfs (st); printf ("%d\n",path.size()-1); int preLine=line[path[0]*10000+path[1]]; int pre=0; for (int j=0;j<path.size();j++) { if (line[path[j]*10000+path[j+1]]!=preLine) { printf ("Take Line#%d from %04d to %04d.\n",preLine,path[pre],path[j]); pre=j; preLine=line[path[j]*10000+path[j+1]]; } } } return 0; }