Official

I - くねくね Editorial by kaage


前に動いた方向が上下か左右かと場所を持って BFS すればよいです。 頂点を倍化して辺を張る方向を変える、という考え方もあります。

#include <algorithm>
#include <iostream>
#include <queue>
#define rep(i, n) for(int i = 0; i < int(n); i++)
using P = std::pair<int, int>;
constexpr int INF = 1e9;
int H, W, sx, sy, gx, gy;
char S[2010][2010];
int dist[2010][2010][2];
int main() {
	std::cin >> H >> W >> sx >> sy >> gx >> gy;
	sx--;
	sy--;
	gx--;
	gy--;
	rep(i, H) rep(j, W) std::cin >> S[i][j];
	std::queue<std::pair<P, bool>> que;
	rep(i, H) rep(j, W) rep(k, 2) dist[i][j][k] = INF;
	que.push({{sx, sy}, false});
	que.push({{sx, sy}, true});
	dist[sx][sy][0] = dist[sx][sy][1] = 0;
	while (!que.empty()) {
		auto p = que.front();
		que.pop();
		if (!p.second) {
			auto [nx, ny] = p.first;
			nx--;
			if (0 <= nx && S[nx][ny] != '#' && dist[nx][ny][1] == INF) {
				dist[nx][ny][1] = dist[p.first.first][p.first.second][0] + 1;
				que.push({{nx, ny}, 1});
			}
			nx += 2;
			if (nx < H && S[nx][ny] != '#' && dist[nx][ny][1] == INF) {
				dist[nx][ny][1] = dist[p.first.first][p.first.second][0] + 1;
				que.push({{nx, ny}, 1});
			}
		} else {
			auto [nx, ny] = p.first;
			ny--;
			if (0 <= ny && S[nx][ny] != '#' && dist[nx][ny][0] == INF) {
				dist[nx][ny][0] = dist[p.first.first][p.first.second][1] + 1;
				que.push({{nx, ny}, 0});
			}
			ny += 2;
			if (ny < W && S[nx][ny] != '#' && dist[nx][ny][0] == INF) {
				dist[nx][ny][0] = dist[p.first.first][p.first.second][1] + 1;
				que.push({{nx, ny}, 0});
			}
		}
	}
	int ans = std::min(dist[gx][gy][0], dist[gx][gy][1]);
	if (ans == INF)
		std::cout << -1 << std::endl;
	else
		std::cout << ans << std::endl;
	return 0;
}

posted:
last update: