Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonでグリッドの左上から右下までの移動経路数を求めるアルゴリズム

N × M の2値行列を考えます。ここで、0は空きセル(通過可能)、1はブロックされたセル(通過不可)を表します。左上の角からスタートして、右下の角に到達するまでの移動方法が何通りあるかを求めます。答えが非常に大きくなる場合は、10^9 + 7 で剰余を取ります。

例えば、入力が以下のような行列だったとします。

001
000
110

この場合の出力は 2 になります。右下に到達できる経路は「右 → 下 → 右 → 下」と「下 → 右 → 右 → 下」の2通りしかないためです。

解法のアプローチ:動的計画法(DP)

この問題は、動的計画法(Dynamic Programming)を使うことで効率的に解けます。各セルに「そのセルに到達できる経路数」を記録していき、左上から順に累積させていくのがポイントです。手順は以下の通りです。

  • 元の行列と同じサイズのDPテーブル dp を作成し、すべて0で初期化します。
  • dp[0][0] := 1 とします(スタート地点には1通りの到達方法がある)。
  • 1行目以降の最初の列について処理します。
    • matrix[i][0] が1なら、そこでループを抜けます(それより先は到達不可能)。
    • そうでなければ、dp[i][0] := 1 とします。
  • 同様に、最初の行の各列についても処理します。
    • matrix[0][j] が1なら、ループを抜けます。
    • そうでなければ、dp[0][j] := 1 とします。
  • 残りの全セルについて、次のようにDPテーブルを埋めていきます。
    • matrix[i][j] が1(ブロックされている)なら、dp[i][j] := 0。
    • そうでなければ、dp[i][j] := dp[i-1][j] + dp[i][j-1](上から来る経路数 + 左から来る経路数)。
  • 最後に、dp の右下の値を返します。

Pythonでの実装例

理解を深めるために、以下の実装を見てみましょう。

class Solution:
    def solve(self, matrix):
        dp = [[0] * len(matrix[0]) for _ in range(len(matrix))]
        dp[0][0] = 1
        for i in range(1, len(matrix)):
            if matrix[i][0] == 1:
                break
            else:
                dp[i][0] = 1
        for j in range(1, len(matrix[0])):
            if matrix[0][j] == 1:
                break
            else:
                dp[0][j] = 1
        for i in range(1, len(matrix)):
            for j in range(1, len(matrix[0])):
                if matrix[i][j] == 1:
                    dp[i][j] = 0
                else:
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
        return dp[-1][-1]
ob = Solution()
matrix = [
    [0, 0, 1],
    [0, 0, 0],
    [1, 1, 0]
]
print(ob.solve(matrix))

入力

matrix = [
[0, 0, 1],
[0, 0, 0],
[1, 1, 0] ]

出力

2

計算量について

このアルゴリズムの時間計算量は O(N × M)、空間計算量も O(N × M) です。行列のサイズに比例して処理が増えるため、大きなグリッドでも効率的に経路数を求められます。なお、経路数が大きくなる可能性がある場合は、各加算後に 10^9 + 7 の剰余を取ることでオーバーフローを防げます。

  1. Pythonで迷路の右下隅に到達するまでの最小マス数を求めるプログラム

    0が空きマス、1が壁を表す2次元グリッド(迷路)があるとします。左上の grid[0][0] からスタートし、グリッドの右下隅に到達するまでに通過する必要のあるマスの最小数を求めます。もし右下隅に到達できない場合は −1 を返します。例えば、入力が以下のような場合を考えてみましょう。000100100この場合、出力は 5 となります。解法のアプローチ:幅優先探索(BFS)この問題は幅優先探索(BFS)を使うことで効率的に解けます。BFSは最短経路を求めるのに適したアルゴリズムで、各セルに到達した時点での移動回数を記録しながら探索を進めます。具体的な手順は以下の通りです。R := グリッドの行数

  2. Pythonでエンコードされたメッセージのデコード方法の総数を求めるプログラム

    問題の概要「a」= 1、「b」= 2、…「z」= 26 というアルファベットと数字の対応関係があるとします。このとき、エンコードされたメッセージ(数字列)が与えられれば、そのメッセージをデコードできる方法が何通りあるかを数えるのが本記事のテーマです。例えば、入力が message = 222 の場合、出力は 3 になります。これは次の3通りにデコードできるためです。b・b・b(2, 2, 2)b・v(2, 22)v・b(22, 2)解決のアプローチ:動的計画法(DP)この問題は動的計画法を用いることで効率的に解くことができます。各位置 i までの文字列についてデコード方法の総数を記録し、1文字