Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

この for ループの処理は、「マス (i, j) に何通りの方法でたどり着けるか」を 上と左のマスからの経路数の合計 を使って計算しています。
動的計画法の定番のパターンです。

ここではを使って処理のイメージを解説します。


💡前提

  • 白いマス(.)は通行可能。
  • 黒いマス(#)は通行不可能。
  • 移動は または のみ。
  • スタートは (0,0)

🎨 処理のイメージ図

仮に以下のような 3×3 のマスがあるとします(S はスタート、G はゴール):

S . .
. # .
. . G

対応する grid は:

grid = [
    ['.', '.', '.'],
    ['.', '#', '.'],
    ['.', '.', '.'],
];

このとき、dp[i][j] を動的に次のように更新していきます。


🧮 DP 配列の初期状態(すべて 0)

[0, 0, 0]
[0, 0, 0]
[0, 0, 0]

ただしスタート地点(白なので)は初期化しておきます:

[1, 0, 0]
[0, 0, 0]
[0, 0, 0]

🔁 for 文での処理フロー

1. マス (0,1)

  • 上から来れない(i == 0
  • 左からは dp[0][0] = 1 なので、ここは 1
[1, 1, 0]

2. マス (0,2)

  • 上から来れない
  • 左から dp[0][1] = 1
[1, 1, 1]

3. マス (1,0)

  • 左から来れない
  • 上から dp[0][0] = 1
[1, 1, 1]
[1, 0, 0]

4. マス (1,1) → #なのでスキップ

[1, 1, 1]
[1, 0, 0]

5. マス (1,2)

  • 上から dp[0][2] = 1
  • 左は dp[1][1] = 0(ここが黒マスだったから通れない) 合計 → 1
[1, 1, 1]
[1, 0, 1]

6. マス (2,0)

  • 上から dp[1][0] = 1
[1, 1, 1]
[1, 0, 1]
[1, 0, 0]

7. マス (2,1)

  • 上:dp[1][1] = 0
  • 左:dp[2][0] = 1 → 合計:1
[1, 1, 1]
[1, 0, 1]
[1, 1, 0]

8. マス (2,2)(ゴール)

  • 上:dp[1][2] = 1
  • 左:dp[2][1] = 1 → 合計:2
[1, 1, 1]
[1, 0, 1]
[1, 1, 2]

✅ 結果:dp[2][2] = 2

つまり (0,0)(2,2) に行く方法は 2通り


🔁まとめ:このループの意味

for (let i = 0; i < H; i++) {
    for (let j = 0; j < W; j++) {
        if (grid[i][j] === '#') continue; // 黒マスはスキップ

        if (i > 0) {
            dp[i][j] += dp[i - 1][j]; // 上から来る通り数
        }

        if (j > 0) {
            dp[i][j] += dp[i][j - 1]; // 左から来る通り数
        }
    }
}

これは:

  • 今のマスに到達する方法の数 = 上から来る数 + 左から来る数
  • 黒マスは通れないから無視

という形で、最終的に (H-1, W-1) に何通りのルートがあるかを計算しています。



📥 入力例

4 8
.....#..
........
..#...#.
#.......

🧩 マス配置 (白=.、黒=#)

インデックス (i, j) を付けて見てみましょう。

(0,0) (0,1) (0,2) (0,3) (0,4) (0,5) (0,6) (0,7)
   .     .     .     .     .     #     .     .

(1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7)
   .     .     .     .     .     .     .     .

(2,0) (2,1) (2,2) (2,3) (2,4) (2,5) (2,6) (2,7)
   .     .     #     .     .     .     #     .

(3,0) (3,1) (3,2) (3,3) (3,4) (3,5) (3,6) (3,7)
   #     .     .     .     .     .     .     .

✅ 目標:

マス (0,0) から右または下だけで、マス (3,7) にたどり着く経路の数を求める。


🧮 処理手順(DP配列を使う)

初期状態

最初のスタート地点 (0,0) は白なので、1通り

dp[0][0] = 1

⬇️ 処理を進めながら DP 配列を更新していく

以下は計算後の dp 配列の完成版#のところは通れないから0):

[1, 1, 2, 3, 4, 0, 4, 8]
[1, 2, 4, 7,11,11,15,23]
[1, 3, 0, 7,18,29, 0,23]
[0, 3, 3,10,28,57,72,95]

✨ 各マスの意味

  • 例えば (2,5) = 29
    → マス (0,0) から (2,5) にたどり着くルートが 29通りあるという意味です。
  • 最後のマス (3,7) = 95通り

🧠 ポイントのあるマスの説明

(0,5) は # → 通れない → dp[0][5] = 0

[1, 1, 2, 3, 4, 0, 4, 8]

(2,2) は # → 通れない → dp[2][2] = 0

(2,6) も #dp[2][6] = 0

(3,0) も #dp[3][0] = 0


📊 最終出力:

dp[3][7] = 95

なので、答えは 95 通り


🧩 補足:処理の流れの例(簡易)

例えばマス (1,2) を処理する場合:

  • 上から:dp[0][2] = 2
  • 左から:dp[1][1] = 2
  • 合計:2 + 2 = 4

🏁 まとめ

この入力に対しては:

  • スタート地点 (0,0) から
  • 黒マスを避けながら
  • 右・下だけの動きで
  • ゴール (3,7) にたどり着く方法は

👉 **「95通り」**です!