// gemini 3.1pro #include #include #include using namespace std; int main() { // 入出力の高速化 ios_base::sync_with_stdio(false); cin.tie(NULL); int H, W; if (!(cin >> H >> W)) return 0; vector grid(H); for (int i = 0; i < H; i++) { cin >> grid[i]; } // 4つの状態 × H × W の最大ノード数 int max_nodes = 4 * H * W; // 距離配列(-1で未訪問を管理) vector dist(max_nodes, -1); // 高速なキュー(vectorで代用) vector q(max_nodes); int head = 0, tail = 0; // 次の状態をキューに追加するラムダ式 auto push = [&](int d, int ntype, int nr, int nc) { // 範囲外チェック if (nr < 0 || nc < 0) return; if (ntype == 0 && (nr >= H || nc >= W)) return; if (ntype == 1 && (nr >= H - 1 || nc >= W)) return; if (ntype == 2 && (nr >= H || nc >= W - 1)) return; if (ntype == 3 && (nr >= H - 1 || nc >= W - 1)) return; // 通常状態の場合は壁をチェック if (ntype == 0 && grid[nr][nc] == '#') return; int v = ntype * H * W + nr * W + nc; if (dist[v] == -1) { dist[v] = d + 1; q[tail++] = v; } }; // スタート地点 (タイプ0, 0行目, 0列目) int start_id = 0 * H * W + 0 * W + 0; dist[start_id] = 0; q[tail++] = start_id; while (head < tail) { int u = q[head++]; int type = u / (H * W); int rem = u % (H * W); int r = rem / W; int c = rem % W; int d = dist[u]; if (type == 0) { // EE (通常マス) if (r == H - 1 && c == W - 1) { cout << d << "\n"; return 0; } // そのまま移動 push(d, 0, r + 1, c); push(d, 0, r - 1, c); push(d, 0, r, c + 1); push(d, 0, r, c - 1); // 横ハイウェイ(OE)へ降りる push(d, 1, r, c); push(d, 1, r - 1, c); // 縦ハイウェイ(EO)へ降りる push(d, 2, r, c); push(d, 2, r, c - 1); } else if (type == 1) { // OE (横ハイウェイ) // 通常マスへ戻る push(d, 0, r, c); push(d, 0, r + 1, c); // ハイウェイ上を横移動 push(d, 1, r, c - 1); push(d, 1, r, c + 1); // 交差点(OO)へ移動 push(d, 3, r, c); push(d, 3, r, c - 1); } else if (type == 2) { // EO (縦ハイウェイ) // 通常マスへ戻る push(d, 0, r, c); push(d, 0, r, c + 1); // ハイウェイ上を縦移動 push(d, 2, r - 1, c); push(d, 2, r + 1, c); // 交差点(OO)へ移動 push(d, 3, r, c); push(d, 3, r - 1, c); } else if (type == 3) { // OO (交差点) // ハイウェイへ抜ける push(d, 1, r, c); push(d, 1, r, c + 1); push(d, 2, r, c); push(d, 2, r + 1, c); } } // どうやっても到達できない場合 cout << -1 << "\n"; return 0; }