拼多多2018暑期實習招聘線上程式設計題:迷宮尋路

凜冬烈焰發表於2018-05-31

題目描述:一個探險家被困在地底迷宮中,要從當前位置開始找一條通往迷宮出口的路徑。迷宮用一個二維矩陣表示,有的部分是牆,有的部分是路。迷宮之中有的路上還有門,每扇門都在迷宮的某個地方有與之匹配的鑰匙,只有先拿到鑰匙才能開啟門。請幫探險家找到脫困的最短路徑。二維矩陣中,0表示牆,1表示路,2表示起始位置,3表示迷宮出口。大寫字母表示門,小寫字母對應大寫字母所代表的門的鑰匙。

輸入描述:

迷宮的地圖,用二維矩陣表示。第一行是矩陣的行數和列數M和N。後面的M行是矩陣的資料,每一行對應矩陣的一行(中間沒有空格)。M和N都不超過100,門不超過10扇。

輸出描述:路徑的長度,是一個整數。

輸入:

5 5

02111

01a0A

01003

0101B

0b111

輸出:

7

說明:

輸出7,對應的路徑為:(0,1)、(0,2)、(1,2)、(0,2)、(0,3)、(0,4)、(1,4)、(2,4)。無需輸出路徑

走迷宮問題在一般情況下都要求形成一個簡單路徑,也就是說,同一個通道在路徑上最多隻能出現1次。但是這道題不能這樣,因為有時候可能需要到某個地方尋找鑰匙,這樣就需要走回頭路(比如例題中的解答)。這裡要把條件放寬,變成:“同一個通道在路徑上最多可以出現兩次”。

這道題就是典型的迷宮尋路問題,只是有一點小變化:穿過門需要對應的鑰匙。其實很好辦:用一個字串(姑且把它視為鑰匙串)。如果路上遇到鑰匙,就將這把鑰匙加進鑰匙串中。遇到門時,如果鑰匙串中有能開啟這扇門的鑰匙,就可以通過,否則無法通過(視為牆壁)。

下面是我的C++程式碼。為了方便起見,就不按照線上程式設計的要求進行多次重複輸入驗證了,只測試一個輸入。

#include <iostream>
#include <vector>
#include <string>

using namespace std;

void search(const vector<string>& matrix, vector<vector<int>> left, int& result,int startx, int starty, int endx, int endy,string keys, int count, int m, int n) {
	if (startx == endx && starty == endy) {
		//到達終點
		if (count < result) result = count;
	}
	else {
		//從起點往四個方向搜尋
		vector<vector<int>> tmpleft;
		string tmpkeys;
		if (startx + 1 < m && left[startx + 1][starty] > 0) {
			if (matrix[startx + 1][starty] == '1' || matrix[startx + 1][starty] == '2' || matrix[startx + 1][starty] == '3') {
				//是一條普通的可以走通的路,或者到達終點
				tmpleft = left;
				tmpleft[startx + 1][starty] -= 1;
				search(matrix, tmpleft, result, startx + 1, starty, endx, endy, keys, count + 1, m, n);
			}
			else if (matrix[startx + 1][starty] >= 'a'&& matrix[startx + 1][starty] <= 'z') {
				//路上有鑰匙
				tmpleft = left;
				tmpleft[startx + 1][starty] -= 1;
				tmpkeys = keys;
				//撿起鑰匙
				tmpkeys.push_back(matrix[startx + 1][starty]);
				search(matrix, tmpleft, result, startx + 1, starty, endx, endy, tmpkeys, count + 1, m, n);
			}
			else if (matrix[startx + 1][starty] >= 'A'&& matrix[startx + 1][starty] <= 'Z') {
				//遇到一扇門
				//檢查自己有沒有這扇門的鑰匙
				char door = matrix[startx + 1][starty], keytoopen = door - 'A' + 'a';
				int index = keys.find(keytoopen);
				if (index>= 0) {
					//只有找到鑰匙才能繼續往前走
					tmpleft = left;
					tmpleft[startx + 1][starty] -= 1;
					search(matrix, tmpleft, result, startx + 1, starty, endx, endy, keys, count + 1, m, n);
				}
			}
		}
		if (startx - 1 >= 0 && left[startx - 1][starty] > 0) {
			if (matrix[startx - 1][starty] == '1' || matrix[startx - 1][starty] == '2' || matrix[startx - 1][starty] == '3') {
				//是一條普通的可以走通的路,或者到達終點
				tmpleft = left;
				tmpleft[startx - 1][starty] -= 1;
				search(matrix, tmpleft, result, startx - 1, starty, endx, endy, keys, count + 1, m, n);
			}
			else if (matrix[startx - 1][starty] >= 'a'&& matrix[startx - 1][starty] <= 'z') {
				//路上有鑰匙
				tmpleft = left;
				tmpleft[startx - 1][starty] -= 1;
				tmpkeys = keys;
				//撿起鑰匙
				tmpkeys.push_back(matrix[startx - 1][starty]);
				search(matrix, tmpleft, result, startx - 1, starty, endx, endy, tmpkeys, count + 1, m, n);
			}
			else if (matrix[startx - 1][starty] >= 'A'&& matrix[startx - 1][starty] <= 'Z') {
				//遇到一扇門
				//檢查自己有沒有這扇門的鑰匙
				char door = matrix[startx - 1][starty], keytoopen = door - 'A' + 'a';
				int index = keys.find(keytoopen);
				if (index >= 0) {
					//只有找到鑰匙才能繼續往前走
					tmpleft = left;
					tmpleft[startx - 1][starty] -= 1;
					search(matrix, tmpleft, result, startx - 1, starty, endx, endy, keys, count + 1, m, n);
				}
			}
		}
		if (starty + 1 < n && left[startx][starty + 1] > 0) {
			if (matrix[startx][starty + 1] == '1' || matrix[startx][starty + 1] == '2' || matrix[startx][starty + 1] == '3') {
				//是一條普通的可以走通的路,或者到達終點
				tmpleft = left;
				tmpleft[startx][starty + 1] -= 1;
				search(matrix, tmpleft, result, startx, starty + 1, endx, endy, keys, count + 1, m, n);
			}
			else if (matrix[startx][starty + 1] >= 'a'&& matrix[startx][starty + 1] <= 'z') {
				//路上有鑰匙
				tmpleft = left;
				tmpleft[startx][starty + 1] -= 1;
				tmpkeys = keys;
				//撿起鑰匙
				tmpkeys.push_back(matrix[startx][starty + 1]);
				search(matrix, tmpleft, result, startx, starty + 1, endx, endy, tmpkeys, count + 1, m, n);
			}
			else if (matrix[startx][starty + 1] >= 'A'&& matrix[startx][starty + 1] <= 'Z') {
				//遇到一扇門
				//檢查自己有沒有這扇門的鑰匙
				char door = matrix[startx][starty + 1], keytoopen = door - 'A' + 'a';
				int index = keys.find(keytoopen);
				if (index >= 0) {
					//只有找到鑰匙才能繼續往前走
					tmpleft = left;
					tmpleft[startx][starty + 1] -= 1;
					search(matrix, tmpleft, result, startx, starty + 1, endx, endy, keys, count + 1, m, n);
				}
			}
		}
		if (starty - 1 >= 0 && left[startx][starty - 1] > 0) {
			if (matrix[startx][starty - 1] == '1'|| matrix[startx][starty - 1] == '2' || matrix[startx][starty - 1] == '3') {
				//是一條普通的可以走通的路,或者到達終點
				tmpleft = left;
				tmpleft[startx][starty - 1] -= 1;
				search(matrix, tmpleft, result, startx, starty - 1, endx, endy, keys, count + 1, m, n);
			}
			else if (matrix[startx][starty - 1] >= 'a'&& matrix[startx][starty - 1] <= 'z') {
				//路上有鑰匙
				tmpleft = left;
				tmpleft[startx][starty - 1] -= 1;
				tmpkeys = keys;
				//撿起鑰匙
				tmpkeys.push_back(matrix[startx][starty - 1]);
				search(matrix, tmpleft, result, startx, starty - 1, endx, endy, tmpkeys, count + 1, m, n);
			}
			else if (matrix[startx][starty - 1] >= 'A'&& matrix[startx][starty - 1] <= 'Z') {
				//遇到一扇門
				//檢查自己有沒有這扇門的鑰匙
				char door = matrix[startx][starty - 1], keytoopen = door - 'A' + 'a';
				int index = keys.find(keytoopen);
				if (index >= 0) {
					//只有找到鑰匙才能繼續往前走
					tmpleft = left;
					tmpleft[startx][starty - 1] -= 1;
					search(matrix, tmpleft, result, startx, starty - 1, endx, endy, keys, count + 1, m, n);
				}
			}
		}
	}
}


int main()
{
	//輸入迷宮
	int m, n;
	cin >> m >> n;
	int startx, starty, endx, endy;
	vector<string> matrix(m);
	vector<vector<int>> left(m);
	for (int i = 0; i < m; i++) {
		cin >> matrix[i];
		for (int j = 0; j < n; j++) {
			if (matrix[i][j] == '0') left[i].push_back(0);
			else left[i].push_back(2);

			if (matrix[i][j] == '2') {
				startx = i, starty = j;
			}
			if (matrix[i][j] == '3') {
				endx = i, endy = j;
			}
		}
	}
	left[startx][starty] = 1;
	string keys = "";
	int res = INT_MAX;
	search(matrix, left, res, startx, starty, endx, endy, keys, 0, m, n);
	cout << res << endl;
	system("pause");
	return 0;
}



相關文章