链接:https://www.nowcoder.com/questionTerminal/e3fc4f8094964a589735d640424b6a47
来源:牛客网
作者:超蓝の悟空
时间限制:1秒
空间限制:131072K
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N
后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述:
路径的长度,是一个整数
输入例子1:
5 5
02111
01a0A
01003
01001
01111
输出例子1:
7
注意这个是一个长方形的迷宫,我起初太傻了以为是一个正方形的迷宫。这个简单错误不能再犯了
首先这道题是在一个矩阵中寻找最短路径,所以肯定是BFS广度优先遍历,但是key和door的关系我当时没想清楚。
后来网上看到了别人的一个做法,感觉很简单,看来我对BFS的理解还有点不够透彻。这道题的visit[x][y][key]的意义就是横坐标为x,纵坐标为y,钥匙状态为key的点是否访问过。钥匙的状态 就用二进制数表示 最多10 把钥匙 那就是1024,比如我现在有第二把钥匙和第四把钥匙 那么我的钥匙状态就是 0101000000 也就是 320,注意提议中说了最多十把钥匙,也即使用10bit即可表示所有状态,状态数量最大是1024。
经过上述的分析题目就很简单了。
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;
class Point
{
public:
int x, y, key, step;
Point(int xx, int yy,int k,int s)
{
x = xx;
y = yy;
key = k;
step = s;
}
};
int bfs(vector<vector<char>>& a, int startx,int starty)
{
queue<Point> que;
que.push(Point(startx, starty, 0, 0));
vector<vector<int>> dir{ { -1,0 },{ 1,0 },{ 0,1 },{ 0,-1 } };
int visit[105][105][1200] = { 0 };
while (que.empty() == false)
{
auto top = que.front();
que.pop();
//这个放到循环中会出现超时的问题
if (a[top.x][top.y] == '3')
return top.step;
for (auto d : dir)
{
int x = top.x + d[0], y = top.y + d[1];
if (x < 0 || x >= a.size() || y < 0 || y >= a[0].size() || a[x][y] == '0')
continue;
//遇到钥匙去做添加
int key = top.key;
if (a[x][y] >= 'a' && a[x][y] <= 'z')
key = (key | (1 << (a[x][y] - 'a')));
//遇到门去找钥匙
if(a[x][y] >= 'A' && a[x][y] <= 'Z' && (key&(1 << (a[x][y] - 'A'))) == 0)
continue;
//在x和y位置的地方由于key是否访问过
if (visit[x][y][key] == 0)
{
visit[x][y][key] = 1;
que.push(Point(x, y, key, top.step + 1));
}
}
}
return 0;
}
int main()
{
int n,m;
cin >> n>>m;
int x, y;
vector<vector<char>> all(n, vector<char>(m));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> all[i][j];
if (all[i][j] == '2')
{
x = i;
y = j;
}
}
}
int res=bfs(all, x, y);
cout << res << endl;
return 0;
}