華爲機試題(地鐵換乘,圖的應用)

1.題目描述

       描述: 已知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 B10 T2 B11 B12 B13 B14 B15

        輸入: 輸入兩個不同的站名
        輸出: 輸出最少經過的站數,含輸入的起點和終點,換乘站點只計算一次
 
        樣例輸入: A1 A3
        樣例輸出: 3


2.題目分析

        題意如圖1所示,本題關鍵是B5、B6,A9、A10,B10、B11,A13、A14不連續,中間有相交點,另有上下兩個環。當然不用圖論算法,也可以解答本題。只不過,要列出所有可能的情況,在短時間內,難免考慮的全面。作者之前就是考慮不用圖做的,但做到最後,幾個小時,一直有幾個測試用例通過不了,考慮不全面。當然,實驗室的其他同學也遇到過類似的問題。當問題的規模增加,如增加幾條線路,那麼這種方法,就不再好用呢。一是代碼量線性增加,若列出所有情況,邏輯上也容易出錯。

        因此,便對此題深入研究了一下,訴之於圖論算法,當然也不需要特別高深的圖論算法,最簡單的圖的最短路徑廣度優先算法就夠了。下面予以實現。

                                                                                    圖1

3.圖論的預備知識

3.1圖的表示

       因爲,本文采用鄰接表來表示圖的,所有僅介紹圖的鄰接表表示,圖的鄰接矩陣表示請參看其他資料。圖9-1,圖9-2分別是有向圖和其鄰接表。表頭爲定點,表的內容爲與其相鄰的頂點,方向爲表頭到表中的內容。(注:圖9-1,圖9-2來自數據結構與算法分析C++第三版)

3.2無權最短路徑的廣度優先搜索

       無權最短路徑的廣度優先搜索見圖9-13,圖9-14,圖9-18,下面採用這種算法解答本題。

4.本題解答

1)頭文件和數據結構:

        代碼中有兩個map變量,vertex採用multimap來使車站和鄰接的車站關聯起來,v_dst使車站和起點到該車站的最短距離關聯起來。

#include <queue>
#include <string>
#include <iostream>
#include <map>
using namespace std;
struct gragh
{
	multimap<string,string> vertex;
	map<string,int> v_dst;
};
typedef multimap<string,string>::iterator it;

 

2)建立鄰接表

     鄰接表的建立是通過掃描字符串來實現的。具體如下:

void builttable(gragh &gar,string a)
{
	string temp1,temp2;
	for (int i=0;i<a.size();++i)
	{
		if (a[i]==' '||i==a.size()-1)
		{
			gar.v_dst.insert(make_pair(temp2,0));
			if (!temp1.empty())
			{
			 gar.vertex.insert(make_pair(temp2,temp1));
			 gar.vertex.insert(make_pair(temp1,temp2));
			}
			temp1=temp2;
			temp2.clear();
		}else
		temp2+=a[i];
	}
}


3)圖的最短路徑搜索

       圖的最短路徑搜索採用圖9-18的算法,簡潔明瞭,其中itm1,itm2分別是輸入的兩個車站。代碼如下:

int searchgragh(gragh &gar,string itm1,string itm2)
{
	map<string,int> v_dst=gar.v_dst;
	queue<string> q1;
	q1.push(itm1);
	v_dst.find(itm1)->second=1;//不可重複插,這個要注意用熟練
	string temp;
	while(!q1.empty())
	{
		temp=q1.front();
		q1.pop();
		it beg=gar.vertex.lower_bound(temp);
		while(beg!=gar.vertex.upper_bound(temp))
		{
			if (!v_dst.find(beg->second)->second)
			{
				v_dst.find(beg->second)->second=v_dst.find(temp)->second+1;
				q1.push(beg->second);
			}
			++beg;
			if (v_dst.find(itm2)->second)
               return v_dst.find(itm2)->second;
		}
	}
	return 0;
}

      主函數如下:

int main()
{
  gragh gra;
  string loopxian("A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 A16 A17 A18 ");
  string line("B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B10 T2 B11 B12 B13 B14 B15 ");
  string a,b;
  int dist;
  builttable(gra,loopxian);
  builttable(gra,line);
  builttable(gra,"A1 A18 ");
	while(1)
	{
		cin>>a>>b;
		dist=searchgragh(gra,a,b);
		cout<<a<<" "<<b<<" "<<dist<<endl;
		system("pause");
	}
       return 0;
}

5.結果

       本人用兩種方案,所得結果如下:(僅列出部分)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章