一只竹鼠正处在由 N × M 个房间组成的矩阵迷宫中,它需要尽快逃出去,否则可能会变得抑郁,然后被农华兄弟吃掉。
为了描述方便,我们把左上角的房间的坐标定为 (0, 0),右下角房间的坐标定为 (N - 1, M - 1)。每个房间可能是 3
种状态之一:开放的、关闭的、或者上锁的。开放房间用 ‘.’ 表示。竹鼠可以随意进入任何一个开放房间。
关闭房间用 ‘#’ 表示。竹鼠永远不能进入一个关闭的房间。
上锁的房间用大写字母 (‘A’, ‘B’, ‘C’, …)
表示。在取得相应的钥匙前不能进入上锁的房间,而一旦取得钥匙就可以反复进入上锁的房间。每个房间的锁都是不同的,相应的钥匙在迷宫中的某一房间里,竹鼠进入该房间就可以取得钥匙。一个房间最多只有一把锁,一个房间里最多只有一把钥匙。竹鼠一开始处于一个开放房间,坐标 (a, b)。迷宫的出口是一个开放或者上锁的房间,坐标 (c,
d)。假设竹鼠每移动到一个相邻房间(上下左右)需要花费 1 单位的时间,那么这只竹鼠到达出口最少需要花费多少时间?
题目包含多组测试数据。第一行包括一个正整数 T,代表测试数据的组数。
接下来的输入,对于每组测试数据:
第 1 行包含 7 个整数: N, M, K, a, b, c, d。其中 N, M 是矩阵的行列数;K 是上锁的房间数目,(a, b)
是起始位置,(c, d) 是出口位置。(1 ≤ N, M ≤ 100; 0 ≤ K ≤ 5; 0 ≤ a, c < N; 0 ≤ b, d
< M)第 2 行到第 N + 1 行,每行包含 M 个字符,表示迷宫矩阵。
第 N + 2 行到第 N + K + 1 行,每行两个整数 x, y,依次表示上锁房间 A, B, C, … 的钥匙所在房间坐标。(0
≤ x < N, 0 ≤ y < M)
对于每组输入,输出到达出口的最短时间。如果这只竹鼠永远到达不了出口,输出 -1。
2
4 4 2 0 0 0 3
.A.B
.#…
.#…
.#…
3 0
3 3
5 5 3 0 0 0 3
.A.B.
.#…
.#…
.#…
…#.C
3 0
4 4
4 1
15
23
bfs模板题,难就难在搜索过程中的状态表示,我比较菜,就直接把vis[maxn][maxn]数组换成了vis[maxn][maxn][2][2][2][2][2],前两个是坐标,后五个是有没有A、B…对应的钥匙,取值0或1,然后就是套bfs的板子
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 107;
char mp[maxn][maxn];
bool vis[maxn][maxn][2][2][2][2][2];
map<P, char> key_room;
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int n, m, k, a, b, c, d;
struct node {
int x, y, step;
int key[5];
};
queue<node> q;
inline bool is_in(int x, int y) {
return x>=0&&x<n&&y>=0&&y<m;
}
int bfs() {
node t;
t.x=a;
t.y=b;
t.step=0;
fill(t.key, t.key+5, 0);
for (int i=0;i<k;i++) {
if (key_room[P(a, b)] >= 'A' && key_room[P(a, b)] <= 'E') {
t.key[key_room[P(a, b)] - 'A'] = 1;
break;
}
}
vis[t.x][t.y][t.key[0]][t.key[1]][t.key[2]][t.key[3]][t.key[4]] = true;
q.push(t);
while (!q.empty()) {
node tp = q.front();q.pop();
for (int i=0;i<4;i++) {
int nxtx=tp.x+dx[i], nxty=tp.y+dy[i];
t = tp;
if (!is_in(nxtx, nxty)) continue;//越界了
if (mp[nxtx][nxty] == '#') continue;//#不能走
if (vis[nxtx][nxty][t.key[0]][t.key[1]][t.key[2]][t.key[3]][t.key[4]]) continue;//之前走过了
if (mp[nxtx][nxty]>='A' && mp[nxtx][nxty]<='E' && tp.key[mp[nxtx][nxty] - 'A' ] == 0) continue;//没钥匙
if (key_room.count(P(nxtx, nxty))) {//拿钥匙
t.key[key_room[P(nxtx, nxty)] - 'A' ] = 1;
}
if (nxtx == c && nxty == d) {//到终点了
return tp.step+1;
}
t.x=nxtx;
t.y=nxty;
t.step=tp.step+1;
vis[nxtx][nxty][t.key[0]][t.key[1]][t.key[2]][t.key[3]][t.key[4]]=true;
q.push(t);
}
}
return -1;
}
int main()
{
int T, tx, ty;
scanf("%d", &T);
while (T--) {
//清理数据
memset(vis, 0, sizeof(vis));
key_room.clear();
while (!q.empty()) {q.pop();}
scanf("%d %d %d %d %d %d %d", &n, &m, &k, &a, &b, &c, &d);
for (int i=0;i<n;i++) {
scanf("%s", mp[i]);
}
for (int i=0;i<k;i++) {
scanf("%d %d", &tx, &ty);
key_room[P(tx, ty)] = i + 'A';
}
printf("%d\n", bfs());
}
return 0;
}
ps:这题是18年南信大的校赛题,当年我才大一,连bfs都不会(虽然现在也很菜)