0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今回は paiza の「時刻に伴う移動」の問題に挑戦!

これが初の「Aランク」問題かも?!


問題概要

へびが 10×10 などのマップの上を動く。
はじめは 北向き(N) で、最大 100 回(時刻 0〜99) 移動する。


🔹 1. 入力されるもの

基本情報

  • マップの行数:H
  • マップの列数:W
  • 初期位置:(sy, sx)
  • 方向転換の回数:N

マップ

  • HW列の文字列
  • '.' は移動可能
  • '#' は障害物(移動不可)

方向転換の予定

  • N 行のデータ:
    • 時刻 t_i
    • 曲がる方向 d_i(L = 左、R = 右)
      t_i は昇順で来る

🔹 2. 移動ルール

◆ 各時刻 i(0〜99)での処理

  • 方向転換の時刻なら
    → 指定の L / R に向きを変更してから 1マス動く
  • 方向転換でないなら
    → 今の向きにそのまま 1マス動く

🔹 3. 移動が「可能」かどうか

次の条件を両方満たすこと:

  • 移動先が マップ外でない
  • 移動先が 障害物 (# でない

🔹 4. 出力

  • 各移動が成功したら、その時点の座標 (y, x) を出力
  • 移動できなかった瞬間
    "Stop" を出力して終了

最大 100 行。



入力例:

10 10 5 5 22
........#.
..........
..........
..........
#.........
..........
..........
........#.
..........
..........
0 L
3 R
4 L
7 L
10 R
12 R
21 L
24 L
26 R
28 R
35 L
36 R
41 R
44 R
62 L
63 L
72 L
81 L
85 R
90 R
92 R
98 R

出力例:

5 4
5 3
5 2
4 2
4 1
Stop






✅OK例:

const rl = require('readline').createInterface({ input: process.stdin });

const lines = [];

rl.on('line', input => lines.push(input));

rl.on('close', () => {
    const [H, W, sy, sx, N] = lines[0].split(' ').map(Number);
    const gridS = lines.slice(1, H+1).map(line => line.split(''));
    const moves = lines.slice(H+1).map(line => line.split(' '));
    
    let x = sx;
    let y = sy;
    
    const turn = {
        N: { L: 'W', R: 'E'},
        S: { L: 'E', R: 'W'},
        E: { L: 'N', R: 'S'},
        W: { L: 'S', R: 'N'}
    }
    
    const dy = { N: -1, S: 1, E: 0, W: 0 };
    const dx = { N: 0, S: 0, E: 1, W: -1 };
    
    let dir = 'N';
    let count = 0;
    
    for (let i = 0; i < 100; i++) {
        const t = Number(moves[count][0]);
        const d = moves[count][1];
        
        // 方向転換をおこなう時刻の場合
        if (i === t) {
            dir = turn[dir][d];
            count++;
        }
        
        
        y += dy[dir];
        x += dx[dir];
        
        if (y < 0 || y >= H || x < 0 || x >= W || gridS[y][x] === '#') {
            console.log('Stop');
            return;
        } else {
            console.log(y, x);
        }
     }
});

🧭 このコードの流れ

  1. 入力を受け取る
    • 1 行目:H, W, sy, sx, N
    • 次の H 行:マップ . / #
    • 残り N 行:方向転換時刻 t_i と向き d_i
  2. 初期設定
    • 現在位置 (y, x) を sy, sx にセット
    • 初期向き dir = 'N'
    • 方向転換を読むインデックス count = 0
  3. 方向転換表 turn を作る(今の向き × L/R → 新しい向き)
  4. 各向きごとの移動量 dy, dx を用意
  5. 時刻 0〜99 をループでまわす(最大 100 回移動)
  6. 今の時刻 i が方向転換予定時刻か確認
    • i === moves[count][0] の場合
      • 指定された方向 (L または R) に向きを変更
      • count++ で次の方向転換へ
  7. 向き dir にしたがって 1 マス移動(y, x を更新)
  8. 移動が可能かチェック
    • マップ外なら Stop
    • '#' なら Stop
  9. 移動が成功したら新しい y, x を出力
  10. 移動不能になった時点で終了






📝まとめ

◆ 1. 時刻

  • 時刻 i に応じて、
  • i == t_j なら方向転換を行う

◆ 2. 方向の管理(N / E / S / W の更新)

  • L / R でどう変わるかを辞書(オブジェクト)で管理するのが楽。
  • 今回の turn オブジェクトが便利。

◆ 3. dy, dx で座標を簡潔に動かす

  • 向きごとの移動量を dy/dx オブジェクト化するとコードを圧縮できる。

◆ 4. 配列を使ったマップ処理

  • grid[y][x] で障害物チェック
  • 2次元マップの基本処理が身につく。

◆ 5. 境界チェック

範囲外アクセスは絶対 NG

  • 0 <= y < H
  • 0 <= x < W
    という典型的な 2D の境界条件。

◆ 6. シミュレーション問題での終了条件

  • 移動不可になった瞬間に Stop
  • 以降の処理はしない(return で早期終了)

◆ 7. 方向転換の入力が複数回あるときの管理

  • count 変数で「次の方向転換はどれか」を追跡




僕の失敗談(´;ω;`)と解決法🐈

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?