D - Synchronized Players Editorial by en_translator
Prepare a graph with \(N^4\) vertices, whose vertices are numbered with four-tuple of integers between \(1\) and \(N\).
When the two player’s positions are \((x_1,y_1)\) and \((x_2, y_2)\), if operating once makes them \((x'_1, y'_1)\) and \((x'_2, y'_2)\) respectively, then add an edge from \((x_1, y_1, x_2, y_2)\) to \((x'_1, y'_1, x'_2, y'_2)\). (Otherwise, do not add an edge.)
Let \((X_1, Y_1)\) and \((X_2, Y_2)\) be the positions of the initial positions of the players; then the minimum number of operations required for the two players to gather at \((i, j)\) is the shortest path from \((X_1, Y_1, X_2, Y_2)\) to \((i, j, i, j)\). (Also note that the two players cannot gather at \((i,j)\) if and only if there is no path to \((i, j, i, j)\).)
Since the graph has \(O(N^4)\) vertices and edges, one can use BFS (Breadth-First Search) for a total time complexity of \(O(N^4)\).
Sample code
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
const int inf = 1000000010;
int dx[] = { -1,0,1,0 }; int dy[] = { 0,1,0,-1 };
int main() {
int n;
cin >> n;
vector<vector<char>> s(n, vector<char>(n));
rep(i, n) rep(j, n) cin >> s[i][j];
vector dis(n, vector(n, vector(n, vector(n, inf))));
int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
rep(i, n) rep(j, n) if (s[i][j] == 'P') {
if (x1 == -1) x1 = i, y1 = j;
else x2 = i, y2 = j;
}
queue<array<int, 4>> que;
dis[x1][y1][x2][y2] = 0;
que.push({ x1,y1,x2,y2 });
while (!que.empty()) {
array<int, 4> ar = que.front(); que.pop();
rep(d, 4) {
array<int, 4> nxt = ar;
nxt[0] += dx[d], nxt[1] += dy[d];
if (0 > nxt[0] or nxt[0] >= n or 0 > nxt[1] or nxt[1] >= n or s[nxt[0]][nxt[1]] == '#') {
nxt[0] = ar[0], nxt[1] = ar[1];
}
nxt[2] += dx[d], nxt[3] += dy[d];
if (0 > nxt[2] or nxt[2] >= n or 0 > nxt[3] or nxt[3] >= n or s[nxt[2]][nxt[3]] == '#') {
nxt[2] = ar[2], nxt[3] = ar[3];
}
if (dis[nxt[0]][nxt[1]][nxt[2]][nxt[3]] == inf) {
dis[nxt[0]][nxt[1]][nxt[2]][nxt[3]] = dis[ar[0]][ar[1]][ar[2]][ar[3]] + 1;
que.push(nxt);
}
}
}
int ans = inf;
rep(i, n) rep(j, n) ans = min(ans, dis[i][j][i][j]);
cout << (ans == inf ? -1 : ans) << '\n';
}
posted:
last update: