を使用して動的プログラミングを適用する
19019 ワード
動的計画法とは
動的計画法(DP)は再帰の最適解である.再帰関数を使用する場合は、入力値を複数回呼び出して処理することができます.この問題を回避するために、全ての計算結果をテーブル(DPテーブル)に格納してもよい.このようにして、DPテーブルの項目にアクセスすることで入力値の結果を見つけ、再計算する必要はありません.
x番目のFibonacci数を計算するためのDPの使用
この式でx番目のfibonacci数を計算します.
f(0) = 1
f(1) = 1
f(x) = f(x - 1) + f(x - 2)
再帰実装
Python
def fibonacci(x: int) -> int:
if x < 0:
raise 'Cannot calculate'
if x == 0:
return 1
if x == 1:
return 1
return fibonacci(x - 1) + fibonacci(x - 2)
エリクシールdefmodule Fibonacci do
def perform(x) when x < 0, do: {:error, "Cannot calculate"}
def perform(x) do
{:ok, calculate(x)}
end
def calculate(x) do
IO.inspect("Calculating #{x}")
case x do
0 ->
1
1 ->
1
x ->
calculate(x - 1) + calculate(x - 2)
end
end
end
Xで走らせましょう.iex(3)> Fibonacci.perform(5)
"Calculating 5"
"Calculating 4"
"Calculating 3"
"Calculating 2"
"Calculating 1"
"Calculating 0"
"Calculating 1"
"Calculating 2"
"Calculating 1"
"Calculating 0"
"Calculating 3"
"Calculating 2"
"Calculating 1"
"Calculating 0"
"Calculating 1"
{:ok, 8}
我々は見ることができるように、我々は最終的な結果を得るために15のステップを取ると、多くの入力値は、複数回再計算されます.以下、各入力値の計算回数を説明する.入力値
計算時間
0
3
1
5
2
3
DPテーブルの実装
再計算問題を解決するためにdpテーブルを用いてdpを適用できる.
Python
def fibonacci(x: int) -> int:
if x < 0:
raise 'Cannot calculate'
if x == 0:
return 1
if x == 1:
return 1
dp_table = [0 for _ in range(x + 1)]
dp_table[0] = 1
dp_table[1] = 1
i = 2
while i <= x:
dp_table[i] = dp_table[i - 1] + dp_table[i - 2]
i += 1
return dp_table[x]
あるいは、DPテーブルをビルドするためにdictを使うことができます.def fibonacci(x: int) -> int:
if x < 0:
raise 'Cannot calculate'
if x == 0:
return 1
if x == 1:
return 1
dp_table = {0: 1, 1: 1}
i = 2
while i <= x:
dp_table[i] = dp_table[i - 1] + dp_table[i - 2]
i += 1
return dp_table[x]
エリクシールdefmodule Fibonacci do
def perform(x) when x < 0, do: {:error, "Cannot calculate"}
def perform(x) do
{:ok, calculate(x, 0)}
end
defp calculate(x, index, table \\ %{}) do
IO.inspect("Calculating #{index}")
fibonacci_value =
case index do
0 ->
1
1 ->
1
index ->
table[index - 1] + table[index - 2]
end
if index == x do
fibonacci_value
else
table = Map.put(table, index, fibonacci_value)
calculate(x, index + 1, table)
end
end
end
Xで走らせましょう.iex(3)> Fibonacci.perform(5)
"Calculating 0"
"Calculating 1"
"Calculating 2"
"Calculating 3"
"Calculating 4"
"Calculating 5"
{:ok, 8}
我々は見ることができるように、計算のためのすべての入力値が一度訪れ、我々は最終的な結果を得るためにわずか5歩かかる.また、
Enum.reduce/3
機能を備えたアプローチもあります.defmodule Fibonacci do
def perform(x) when x < 0, do: {:error, "Cannot calculate"}
def perform(0), do: {:ok, 1}
def perform(1), do: {:ok, 1}
def perform(x) do
dp_table =
Enum.reduce(2..x, %{0 => 1, 1 => 1}, fn index, acc ->
Map.put(acc, index, acc[index - 1] + acc[index - 2])
end)
{:ok, dp_table[x]}
end
end
2変数のみの実装
場合によっては、すべての計算されたFibonacci番号を格納する必要はありません.実際には、( x - 1 )- thと( x - 2 )番目の数字を気にします.DPテーブルのためのスペースを減らすために、計算された値をキャッシュするために、2つの変数だけを使用できます.
defmodule Fibonacci do
def perform(x) when x < 0, do: {:error, "Cannot calculate"}
def perform(0), do: {:ok, 1}
def perform(1), do: {:ok, 1}
def perform(x) do
{:ok, calculate(x, 2, 1, 1)}
end
defp calculate(x, index, c_1, c_2) do
fibonacci_value = c_1 + c_2
if index == x do
fibonacci_value
else
calculate(x, index + 1, fibonacci_value, c_1)
end
end
end
結論
dpを用いたx番目fifiacci数計算法を紹介した.DPを使用すると、アプリケーションを高速にDPテーブルで計算時間を節約することによって実行することができます.次の記事では、Elixirで他のDP問題を解決する方法を紹介します.
Reference
この問題について(を使用して動的プログラミングを適用する), 我々は、より多くの情報をここで見つけました https://dev.to/khanha2/apply-dynamic-programing-for-calculating-fibonacci-number-with-elixir-eg1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol