题目链接:点我打开
当时在场上没做出来,没有想到key的处理方法, 场后看了下题解,学到了用位运算来压缩状态的方法,还是对知识的熟练度不够,联想不到,继续加油。
题目分析:
给你一张n行m列的图, 并定义了四种钥匙和门, 想进门必须先取得相应的钥匙,将钥匙的状态压缩后存入key, 然后bfs, 搜到第一个出口即可退出,此时得到的答案即为最短路。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 100 + 10;
const int dc[] = {1, -1, 0, 0};
const int dr[] = {0, 0, 1, -1};
char maze[maxn][maxn];
int r, c, sc, sr, vis[maxn][maxn][20];
struct node {
int r, c, key, step;
};
inline int judge(char c) {
if (c == 'B' || c == 'b') return 1;
if (c == 'Y' || c == 'y') return 2;
if (c == 'R' || c == 'r') return 4;
if (c == 'G' || c == 'g') return 8;
}
void solve() {
memset(vis, 0, sizeof vis);
queue<node> q;
q.push((node){sr, sc, 0, 0});
vis[sr][sc][0] = 1;
while (!q.empty()) {
node u = q.front(); q.pop();
for (int i = 0; i < 4; i ++) {
node v = u;
v.step = u.step + 1;
v.r = u.r + dr[i];
v.c = u.c + dc[i];
if (v.r < 0 || v.c < 0 || v.r >= r || v.c >= c || maze[v.r][v.c] == '#') continue;
if (maze[v.r][v.c] == 'X') { printf("Escape possible in %d steps.\n", v.step); return; }
if (maze[v.r][v.c] <= 'Z' && maze[v.r][v.c] >= 'A') {
if (v.key & judge(maze[v.r][v.c])) {
if (!vis[v.r][v.c][v.key]) {
vis[v.r][v.c][v.key] = 1;
q.push(v);
}
}
}
else if (maze[v.r][v.c] <= 'z' && maze[v.r][v.c] >= 'a') {
v.key |= judge(maze[v.r][v.c]);
if (!vis[v.r][v.c][v.key]) {
vis[v.r][v.c][v.key] = 1;
q.push(v);
}
}
else if (maze[v.r][v.c] == '.' && !vis[v.r][v.c][v.key]) {
vis[v.r][v.c][v.key] = 1;
q.push(v);
}
}
}
printf("The poor student is trapped!\n");
}
int main() {
while (scanf("%d%d", &r, &c) && r) {
getchar();
for (int i = 0; i < r; i ++) {
scanf("%s", maze[i]);
for (int j = 0; j < c; j ++)
if (maze[i][j] == '*')
maze[i][j] = '.', sr = i, sc = j;
}
solve();
}
return 0;
}