题目:假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙。
思路:经典的BFS,状态有三个维:玩家x坐标,玩家y坐标,钥匙的收集状态
其中钥匙的收集状态共2**10=1024种,可以利用位存储,方便判断和运算
#include<iostream>
#include<string>
#include<queue>
using namespace std;
//doors:10(2**10=1024) maze:100*100
char maze[100][100] = { 0 };
bool mask[100][100][1024] = { 0 };
int next[4][2] = { 1,0, 0,1,-1,0,0,-1 };
int M, N;
struct node {
int r, c;
int keyState;
int depth;
node *pre; //to print path
node(int r,int c,int keyState,int depth,node *pre):r(r),c(c),keyState(keyState),depth(depth),pre(pre){}
};
int bfs(node& start);
int main() {
node start=node(0,0,0,0,NULL);
while (cin >> M >> N) {
//input and initiate
for(int i=0;i<M;i++)
for(int j=0;j<N;j++){
cin>>maze[i][j];
if (maze[i][j] == '2') {
start.r = i;
start.c = j;
}
for (int k = 0; k < 1024; k++)
mask[i][j][k] = 0;
}
//calculate
cout << bfs(start) << endl;
}
return 0;
}
BFS部分套用模板
int bfs(node& start) {
queue<node> q;
q.push(start);
mask[start.r][start.c][start.keyState] = 1;
while (!q.empty()) {
node head = q.front();
q.pop();
if (maze[head.r][head.c] == '3') {
return head.depth;
}
for (int i = 0; i < 4; i++) {
int nr = head.r + ::next[i][0];
int nc = head.c + ::next[i][1];
if (nr < 0 || nr >= M || nc < 0 || nr >= N)
continue;
if (maze[nr][nc] == '0')
continue;
int keyState = head.keyState;
//遇到门,但没有对应的钥匙
if (maze[nr][nc] >= 'A'&&maze[nr][nc] <= 'Z' && (1 << (maze[nr][nc] - 'A'))&keyState == 0)
continue;
//捡钥匙
if (maze[nr][nc] >= 'a'&&maze[nr][nc] <= 'z')
keyState = keyState | (1 << (maze[nr][nc] - 'a'));
if (mask[nr][nc][keyState] == 0) {
mask[nr][nc][keyState] = 1;
q.push(node(nr, nc, keyState, head.depth + 1, &head));
}
}
}
return -1;
}