题目链接:https://codeforces.com/contest/1366/problem/C
题意
有一个 $n imes m$ 的 $01$迷宫,要使从 $(1,1)$ 到 $(n,m)$ 的所有路径均为回文串,至少要变换多少字符。
题解一
用 $bfs$ 得到回文串每个位置可能的 $01$ 个数,对称位置变换 $01$ 总个数中的较少值即可。
代码
#include <bits/stdc++.h> using namespace std; const int dir[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; const int N = 100; int n, m; int MP[N][N]; bool vis[N][N]; int cnt[N][2]; bool inside(int x, int y) { return 1 <= x and x <= n and 1 <= y and y <= m; } struct P{ int x, y, dep; }; void bfs() { queue<P> que; que.push({1, 1, 1}); vis[1][1] = true; while (!que.empty()) { int x = que.front().x; int y = que.front().y; int dep = que.front().dep; que.pop(); ++cnt[dep][MP[x][y]]; for (int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; if (inside(nx, ny) and !vis[nx][ny]) { que.push({nx, ny, dep + 1}); vis[nx][ny] = true; } } } } void solve() { memset(vis, 0, sizeof vis); memset(cnt, 0, sizeof cnt); cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> MP[i][j]; bfs(); int tot = n + m - 1; int ans = 0; for (int i = 1; i <= tot / 2; i++) ans += min(cnt[i][0] + cnt[tot - i + 1][0], cnt[i][1] + cnt[tot - i + 1][1]); cout << ans << " "; } int main() { int t; cin >> t; while (t--) solve(); }
题解二
可以用下标计算出当前字符在 $bfs$ 中的层数,即回文串中的位置。
代码
#include <bits/stdc++.h> using namespace std; const int N = 100; int n, m; int cnt[N][2]; void solve() { memset(cnt, 0, sizeof cnt); cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { int x; cin >> x; ++cnt[i + j - 1][x]; } int tot = n + m - 1; int ans = 0; for (int i = 1; i <= tot / 2; i++) ans += min(cnt[i][0] + cnt[tot - i + 1][0], cnt[i][1] + cnt[tot - i + 1][1]); cout << ans << " "; } int main() { int t; cin >> t; while (t--) solve(); }