题目描述
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
输入描述:
迷宫的地图,用二维矩阵表示。第一行是表示矩阵的行数和列数M和N 后面的M行是矩阵的数据,每一行对应与矩阵的一行(中间没有空格)。M和N都不超过100, 门不超过10扇。
输出描述:
路径的长度,是一个整数
思路:记录钥匙状态,压缩就可以,记录是否访问使用x+y+key 的方式。普通广搜或优先级队列都可以。
#include<bits/stdc++.h>
using namespace std;
int n, m;
int bx,by,ex,ey;
char M[505][505];
int vis[105][105][1100];
int dir[4][2] = {0, 1, 1, 0 , 0 , -1 , -1, 0};
struct node
{
int x,y,step,k;
/*bool friend operator<(node n1, node n2)
{
return n1.step > n2.step;
}*/
}cur, tmp;
int BFS()
{
vis[bx][by][0] = 1;
//priority_queue<node>q;
queue<node>q;
cur.x = bx,cur.y = by, cur.step = 0 , cur.k = 0;
q.push(cur);
while(!q.empty())
{
//cur = q.top();
cur = q.front();
q.pop();
if(cur.x == ex && cur.y == ey) return cur.step;
for(int i = 0 ; i < 4 ; i ++)
{
tmp.x = cur.x + dir[i][0];
tmp.y = cur.y + dir[i][1];
tmp.step = cur.step + 1;
tmp.k = cur.k;
if(tmp.x < 0 || tmp.x >= n || tmp.y < 0 || tmp.y >= m || M[tmp.x][tmp.y] == '0') continue;
if(M[tmp.x][tmp.y] >= 'a' && M[tmp.x][tmp.y] <= 'z')
{
tmp.k = tmp.k | (1 << (M[tmp.x][tmp.y] - 'a'));
}
if(M[tmp.x][tmp.y] >= 'A' && M[tmp.x][tmp.y] <= 'Z')
{
if( !(tmp.k & (1 << (M[tmp.x][tmp.y] - 'A')))) continue;
}
if(!vis[tmp.x][tmp.y][tmp.k])
{
vis[tmp.x][tmp.y][tmp.k] = 1;
q.push(tmp);
}
}
}
return -1;
}
int main()
{
while(cin >> n >> m)
{
memset(vis, 0 , sizeof(vis));
for(int i = 0 ; i < n ; i ++)
{
cin >> M[i];
for(int j = 0 ; j < m ; j ++)
{
if(M[i][j] == '2')
{
bx = i;
by = j;
}
if(M[i][j] == '3')
{
ex = i;
ey = j;
}
}
}
cout << BFS() << endl;
}
}