题解:ABC427E Wind Cleaning【BFS】
ABC427E Wind Cleaning
根据相对运动,所有 # 一起移动转换为只有 T 移动。
看这题的第一眼是状态数为 # 出界了之后还可以再回来,而题目要求出界后就被删去了。
那么考虑我们还需要哪些状态才能刻画这一情况。发现只需记录当前所有 # 的 # # 还没被删去,否则已经被删去。
因此写一个
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using UI = unsigned int;
using ULL = unsigned long long;
using DB = double;
using LDB = long double;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
#define CP(x) complex<x>
#define fst first
#define snd second
#define popcnt(i) __builtin_popcount(i)
const int N = 60, C = 20;
int n, m, d[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
bool rec[N][N];
struct Info {
int x, y, minX, maxX, minY, maxY, c;
} s;
map<array<int, 6>, bool> vis;
void chkmax(int &a, int b) { if (b > a) a = b; }
void chkmin(int &a, int b) { if (b < a) a = b; }
bool exist(Info u, int x, int y) {
return (x >= u.minX && x <= u.maxX && y >= u.minY && y <= u.maxY);
}
bool check(Info u) {
int dx = u.x - s.x, dy = u.y - s.y;
for (int i = 1 + dx; i <= n + dx; i++) {
for (int j = 1 + dy; j <= m + dy; j++) {
if (rec[i + C][j + C] && exist(u, i, j)) return 0;
}
}
return 1;
}
void update(Info u, Info &v) {
v.c = u.c + 1;
v.maxX = v.maxY = 0;
v.minX = n + 1, v.minY = m + 1;
int dx = v.x - s.x, dy = v.y - s.y;
for (int i = 1 + dx; i <= n + dx; i++) {
for (int j = 1 + dy; j <= m + dy; j++) {
if (rec[i + C][j + C] && exist(u, i, j)) {
chkmax(v.maxX, i);
chkmax(v.maxY, j);
chkmin(v.minX, i);
chkmin(v.minY, j);
}
}
}
}
void solve() {
cin >> n >> m;
char c;
s = {0, 0, n + 1, 0, m + 1, 0, 0};
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> c;
if (c == 'T') {
s.x = i, s.y = j;
} else if (c == '#') {
rec[i + C][j + C] = 1;
chkmax(s.maxX, i);
chkmax(s.maxY, j);
chkmin(s.minX, i);
chkmin(s.minY, j);
}
}
}
queue<Info> q;
q.push(s);
vis[{s.x, s.y, s.maxX, s.minX, s.maxY, s.minY}] = 1;
while (!q.empty()) {
auto u = q.front();
q.pop();
if (check(u)) {
cout << u.c << '\n';
return;
}
Info v;
for (int i = 0; i < 4; i++) {
v.x = u.x + d[i][0], v.y = u.y + d[i][1];
if (rec[v.x + C][v.y + C] && exist(u, v.x, v.y)) continue;
update(u, v);
if (vis.count({v.x, v.y, v.maxX, v.minX, v.maxY, v.minY})) continue;
vis[{v.x, v.y, v.maxX, v.minX, v.maxY, v.minY}] = 1;
q.push(v);
}
}
cout << -1 << '\n';
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}