Codeforces Round #648 (Div. 2) D. Solve The Maze
这题犯了一个很严重的错误,bfs 应该在入队操作的同时标记访问,而不是每次只标记取出的队首元素。
题目链接:https://codeforces.com/contest/1365/problem/D
题意
有一个 $n \times m$ 的迷宫,迷宫有四种方格:
- '.' 空方格
- '#' 墙
- 'B' 坏人
- 'G' 好人
人与人间可以通行,人与墙间不能,可以把任意空方格变为墙,问能否所有好人可以到达 $(n, m)$ 但所有坏人不能。
题解
无解有两种情况:
- 坏人与好人相邻
- 在每个坏人相邻的四个方格建墙后有好人不能到达终点
用 bfs 或 dfs 模拟即可。
代码
#include <bits/stdc++.h> using namespace std; const int dir[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; const int N = 55; int n, m; char MP[N][N]; bool inside(int x, int y) { return (1 <= x and x <= n) and (1 <= y and y <= m); } bool good(int x, int y) { return MP[x][y] == '.' or MP[x][y] == 'G'; } void bfs() { queue<pair<int, int>> que; que.push({n, m}); MP[n][m] = 'E'; while (!que.empty()) { int x = que.front().first; int y = que.front().second; que.pop(); for (int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; if (inside(nx, ny) and good(nx, ny)) { que.push({nx, ny}); MP[nx][ny] = 'E'; } } } } void solve() { cin >> n >> m; vector<pair<int, int>> G, B; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> MP[i][j]; if (MP[i][j] == 'G') G.push_back({i, j}); if (MP[i][j] == 'B') B.push_back({i, j}); } } bool block = true; for (auto pr : B) { int x = pr.first; int y = pr.second; for (int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; if (MP[nx][ny] == 'G') block = false; if (MP[nx][ny] == '.') MP[nx][ny] = '#'; } } if (good(n, m)) bfs(); bool escape = true; for (auto pr : G) escape &= MP[pr.first][pr.second] == 'E'; cout << (block and escape ? "Yes" : "No") << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }