華為機試—地鐵換乘(圖文吐血整理)
阿新 • • 發佈:2019-02-08
題目:地鐵換乘
描述:已知2條地鐵線路,其中A為環線,B為東西向線路,線路都是雙向的。經過的站點名分別如下,兩條線交叉的換乘點用T1、T2表示。編寫程式,任意輸入兩個站點名稱,輸出乘坐地鐵最少需要經過的車站數量(含輸入的起點和終點,換乘站點只計算一次)。
地鐵線A(環線)經過車站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 A16 A17 A18
地鐵線B(直線)經過車站:B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B1!0 T2 B11 B12 B13 B14 B15
輸入:輸入兩個不同的站名
輸出:所經過的站數及站的名稱
基本思路:
其實分析問題就會發現,這是圖論中的一個求最短路徑的問題,是圖演算法的裡面比較基礎的。常見的求路徑的有A星,Dijkstra演算法,floyd演算法等。
下面用floyd演算法求解,三重迴圈簡單暴力。
floyd演算法剖析:
Floyd演算法的基本思想如下:從任意節點A到任意節點B的最短路徑不外乎2種可能:
1、是直接從A到B,
2、是從A經過若干個節點X到B。
所以,我們假設dis(AB)為節點A到節點B的最短路徑的距離,對於每一個節點X,我們檢查dis(AX) + dis(XB) < dis(AB)是否成立,如果成立,證明從A到X再到B的路徑比A直接到B的路徑短,我們便設定dis(AB)= dis(AX) +dis(XB),這樣一來,當我們遍歷完所有節點X,dis(AB)中記錄的便是A到B的最短路徑的距離。
題目場景:
詳細程式碼,帶列印路徑:
#include<iostream> #include<string> #include<stack> using namespace std; #define inf 1000 //定義無窮遠距離 #define stanum 35 //定義總站臺數 string staName[stanum] = {"A1","A2","A3","A4","A5","A6","A7","A8","A9","A10", "A11","A12","A13","A14","A15","A16","A17","A18", "B1","B2","B3","B4","B5","B6","B7","B8","B9","B10", "B11","B12","B13","B14","B15","T1","T2"} ; //記錄車站的名字 //floyd演算法找出最短路徑 void floyd(int dis[][stanum],int path[][stanum]) { //初始化path矩陣 for(int row=0;row<stanum;row++) for(int col=0;col<stanum;col++) path[row][col]=row; //找最短路徑 for(int k=0;k<stanum;k++) for(int i=0;i<stanum;i++) for(int j=0;j<stanum;j++) if(dis[i][j]>dis[i][k]+dis[k][j]) { dis[i][j]=dis[i][k]+dis[k][j]; path[i][j]=path[k][j]; } } //轉換車站的名字到矩陣的索引 int string2int(string s) { for(int i=0;i<stanum;i++) { if(s==staName[i]) { return i; break; } } return 0; } void printres(int dis[][stanum],int path[][stanum],string start,string dest) { int s; int d; s=string2int(start); d=string2int(dest); cout<<"最少經過的車站數量: "<<dis[s][d]+1<<endl; //輸出站樹加1包括了起始站 cout<<"經過的車站路徑編號: "; for(int i=0;i<stanum;i++) for(int j=0;j<stanum;j++) { if(i==s&&j==d) //輸出路徑 { stack<int> pathrout; //壓棧 int k=j; do{ k=path[i][k]; pathrout.push(k); }while(k!=i); //彈棧 cout<<staName[pathrout.top()]; pathrout.pop(); int length=pathrout.size(); for(int t=0;t<length;t++) { cout<<"->"<<staName[pathrout.top()]; pathrout.pop(); } cout<<"->"<<staName[d]<<endl; break; } } } int main() { int distance[stanum][stanum]; int path[stanum][stanum]; string start; string dest; //初始化連線矩陣 for(int i=0;i<stanum;i++) { for(int j=0;j<stanum;j++) { if(i==j) distance[i][j]=0; else distance[i][j]=inf; } } //初始化技巧 int sa[21]={0,1,2,3,4,5,6,7,8,33,9,10,11,12,34,13,14,15,16,17,0}; for(i=0;i<20;i++) { distance[sa[i]][sa[i+1]]=1; distance[sa[i+1]][sa[i]]=1; } int sb[17]={18,19,20,21,22,33,23,24,25,26,27,34,28,29,30,31,32}; for(i=0;i<16;i++) { distance[sb[i]][sb[i+1]]=1; distance[sb[i+1]][sb[i]]=1; } floyd(distance,path); cout<<"輸入起點和終點: "<<endl; while(cin>>start>>dest){ printres(distance,path,start,dest); printf("\n"); } return 0; }
測試結果,可能想的不周全,歡迎查漏補缺: