Pythonでグリッド上に集められるコインの最大数を求めるプログラム
問題の概要
各セルにコインが置かれた2次元行列(マトリックス)があるとします。左上の [0,0] の位置からスタートし、右または下にのみ移動できるという制約のもとで、右下隅まで移動する過程で収集できるコインの最大数を求めるのがこの問題です。
例として、次のような入力が与えられた場合を考えてみましょう。
| 1 | 4 | 2 | 2 |
| 6 | 0 | 0 | 5 |
この場合、出力は 14 になります。これは、パス [1, 4, 2, 2, 5] を通ることで、合計14枚のコインを集められるためです。
解き方(動的計画法)
この問題は動的計画法(DP)を使うと効率的に解けます。考え方はシンプルで、「あるセルに到達した時点でのコインの最大累積数」は、「そのセル自身のコイン」と「上から来た場合・左から来た場合のうち大きい方」を足したものになります。
具体的には、入力行列 A をそのままDPテーブルとして使い、以下の手順で更新していきます。
まず1列目を処理します。1列目は上からしか来られないため、各行について次のように累積和を求めます。
A[r][0] := A[r][0] + A[r-1][0]次に1行目を処理します。1行目は左からしか来られないため、各列について次のように累積和を求めます。
A[0][c] := A[0][c] + A[0][c-1]残りのすべてのセル [r][c] に対して、上のセル A[r-1][c] と左のセル A[r][c-1] のうち大きい方を現在の値に加算します。
A[r][c] = A[r][c] + max(A[r-1][c], A[r][c-1])最後に、行列の右下隅の値を返します。これが答えとなります。
それでは、実際の実装を見てみましょう。
実装例
class Solution: def solve(self, A): # 1列目の累積和を計算 for r in range(1, len(A)): A[r][0] += A[r-1][0] # 1行目の累積和を計算 for c in range(1, len(A[0])): A[0][c] += A[0][c-1] # 残りのセルを更新 for r in range(1, len(A)): for c in range(1, len(A[0])): A[r][c] += max(A[r-1][c], A[r][c-1]) return A[-1][-1] ob = Solution() matrix = [ [1, 4, 2, 2], [6, 0, 0, 5] ] print(ob.solve(matrix))
入力
matrix = [ [1, 4, 2, 2], [6, 0, 0, 5] ]
出力
14
計算量について
時間計算量: 行数を R、列数を C とすると、すべてのセルを一度ずつ処理するため O(R × C) です。
空間計算量: 入力行列自体をDPテーブルとして再利用しているため、追加のメモリは O(1) で済みます。
このように、動的計画法を使えば、右・下への移動制限があるグリッド上の最適パス問題を効率よく解くことができます。同様の手法は「最小パス和」や「ユニークパス」など、他のグリッド系DP問題にも応用できます。
-
Pythonで二分探索木(BST)の指定範囲内にあるノード数を求める方法
問題の概要 二分探索木(BST)が与えられ、さらに左側の境界値 l と右側の境界値 r が指定されます。このとき、木に含まれるすべてのノードの中で、値が l 以上 r 以下の範囲内にあるノードの個数を求めるのが目的です。 例えば、次のような木が与えられたとします。 このとき l = 7、r = 13 とすると、範囲内に含まれるノードは 8、10、12 の3つなので、出力は 3 になります。 アルゴリズムの考え方 スタックを使った反復的な深さ優先探索(DFS)で木をたどります。重要なポイントは、二分探索木の性質を活かして枝刈り(pruning)を行うことです。値が境界より小さいノードの左側の
-
【Python入門】3つの数値から最大値を求める方法
3つの数値 a、b、c が与えられたとき、その中で最も大きい要素(最大値)を見つけるのが今回の課題です。ここでは、Pythonのリストと組み込み関数 max() を使ったシンプルな方法を、初心者向けにわかりやすく解説します。 実行例 入力:a = 2, b = 4, c = 3 出力:4 アルゴリズム ステップ1:ユーザーから3つの数値を入力として受け取る。 ステップ2:3つの数値をリストに格納する。 ステップ3:max() 関数を使ってリスト内の最大値 max(lst) を求める。 ステップ4:最後に最大値を出力する。 サンプルコード def maximum(a, b, c):