题目描述:一个探险家被困在地底迷宫中,要从当前位置开始找一条通往迷宫出口的路径。迷宫用一个二维矩阵表示,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请帮探险家找到脱困的最短路径。二维矩阵中,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; }