障害物のある格子路の問題解法:動的最適化による経路カウント

m 行 n 列の二次元グリッドが与えられた場合、左上隅の座標から右下隅の座標まで移動するシナリオを考慮します。移動ルールとして、一歩ごとに「下」または「右」へ進むことが許容されています。

この環境には障害物が混在しており、特定のセルは通ることが不可能です。データ構造上、障害物は整数 1、空席は 0 によって定義されます。これらの条件を満たしながら、スタート地点からゴール地点に至る異なる経路の総数を算出する必要があります。

入力と出力例

入力データ:[[0, 0, 0], [0, 1, 0], [0, 0, 0]]
計算結果:2

入力データ:[[0, 1], [0, 0]]
計算結果:1

上記の例において、3x3 の領域中央や 2x2 の領域上部など、いくつかのブロックが存在します。これらの物理的制約がある条件下での組み合わせ数を導き出すのが目的です。

アルゴリズムの設計思想

この種の問題は、動的計画法(Dynamic Programming)を用いることで効率的に解決できます。状態遷移の基本概念として、現在位置への到達方法は「左からの移動」と「上からの移動」の合計になります。
数学的には次の式で表せます:

value[i][j] = value[i-1][j] + value[i][j-1]

ただし、障害物の存在はこの計算フローに影響を与えます。まず、初期化プロセスにおいて慎重な判断が必要です。第一行と第一列については、障害物がない限りパス数が 1 と確定しますが、一度障害物(1)に遭遇すると、それ以降のセルもアクセスできなくなります。そのため、第一行・第一列のループ内では、障害物を検知した時点で以降の初期化を中止(break)する必要があります。

本格的な計算に移る際も同様に、現在のマウスオーバーセルが障害物である場合は、その場所へのパス数はゼロとみなし、加算処理を実行してはいけません。起点となる座標が最初から障害物である場合も、到達不可のため即座に 0 を返却すべきです。

実装コード

以下に、Python を用いた具体的な実装例を示します。内部変数の命名規則を変更し、コード構造を整理しています。

class Solution:
    def find_path_count(self, grid_field):
        total_rows = len(grid_field)
        total_cols = len(grid_field[0])

        # スタート地点が障害物のチェック
        if grid_field[0][0] == 1:
            return 0
        
        # DP テーブルの初期化
        dp_table = [[0 for _ in range(total_cols)] for _ in range(total_rows)]
        
        # 第一列の初期化
        for r in range(total_rows):
            if grid_field[r][0] == 1:
                break
            dp_table[r][0] = 1
            
        # 第一行の初期化
        for c in range(total_cols):
            if grid_field[0][c] == 1:
                break
            dp_table[0][c] = 1

        # メインの DP ループ
        for i in range(1, total_rows):
            for j in range(1, total_cols):
                if grid_field[i][j] == 0:
                    dp_table[i][j] = dp_table[i-1][j] + dp_table[i][j-1]
        
        return dp_table[total_rows-1][total_cols-1]

タグ: dynamic-programming grid-matrix algorithm-design Python3

6月17日 20:42 投稿