「DA:dp」の版間の差分

提供:classwiki
ナビゲーションに移動 検索に移動
34行目: 34行目:
=== 動的計画法 ===
=== 動的計画法 ===


フィボナッチ数列の場合,普通に小さい方から順に計算していくのが動的計画法になっている.長さ n のリスト memo を準備して,0 番目から順に埋めていけば良い.(ただし,以下のプログラムでは n=1 の場合に,リスト memo の長さは 1 なので, "memo[1] = 1" のところでエラーが出てしまう.これを避けるため,memo の長さを n+1 とした.)
フィボナッチ数列の場合,普通に小さい方から順に計算していくのが動的計画法になっている.長さ n のリスト memo を準備して,0 番目から順に埋めていけば良い.(ただし, n=1 の場合に,リスト memo の長さは 1 なので, "memo[1] = 1" のところでエラーが出てしまう.これを避けるため,memo の長さを n+1 とした.)


  def fibonacci_dp(n):
  def fibonacci_dp(n):

2025年3月31日 (月) 00:33時点における版

フィボナッチ数列

全探索

次のコードは,再帰関数を用いた全探索による解法です.ただし,fibonacci 関数の引数 n は正の整数であることを仮定しています.

def fibonacci(n):
    if n == 1 or n == 2:
        return 1
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))

しかしこれは無駄が多い実装です.fobonacci(n) を実行する際に,fibonacci(n-1) と fibonacci(n-2) が実行されますが,fibonacci(n-1) の中でも fibonacci(n-2) がまた実行されることになります.よって,このままでは全く同じ計算を何回も繰り返すことになります.

全探索(既に計算したものをメモしておく戦略)

これを,既に計算したものは結果を保存して使い回す,という戦略で計算してみましょう.ここでは,n=10ならば,長さ10のリストを準備して,その k 番目の要素に fibonacci(k+1) が格納されるようにします.この戦略を実装したものが,次のコードです.

def fibonacci(n):
    if memo[n-1] != 0:
        return memo[n-1]
    a = fibonacci(n-1) + fibonacci(n-2)
    return a

n = 10

memo = [0 for i in range(n+1)]
memo[0] = 1
memo[1] = 1

print(fibonacci(n))

動的計画法

フィボナッチ数列の場合,普通に小さい方から順に計算していくのが動的計画法になっている.長さ n のリスト memo を準備して,0 番目から順に埋めていけば良い.(ただし, n=1 の場合に,リスト memo の長さは 1 なので, "memo[1] = 1" のところでエラーが出てしまう.これを避けるため,memo の長さを n+1 とした.)

def fibonacci_dp(n):
    memo = [0 for i in range(n+1)]
    memo[0] = 1
    memo[1] = 1
    for i in range(2,n):
        memo[i] = memo[i-1] + memo[i-2]
    return memo[n-1]

print(fibonacci_dp(10))