注:文字通りの意味を探すのではなく、動的計画法の名前を使用してアルゴリズムを逆にしてください!実際、動的計画法は、高校のシリーズの質問のアップグレード版のようなものです。
動的計画法で解決できる問題について満たす必要のある2つのポイント
- 大きな問題を小さな問題に分解する
- マイナーな問題は繰り返し呼び出されます
動的計画法を適用する-動的計画法を3つのサブゴールに分割する
1.状態遷移方程式を確立します。
考え:f(1)〜f(n-1)の値を知り、それらを使用してf(n)を見つける方法を見つけます。
2.過去の結果をキャッシュして再利用します
適切な処理がないと、時間の複雑さは指数関数的になる可能性があります
3.小さいものから大きいものの順に計算します
例:
1.フィボナッチ数列(単純)
フィボナッチ数列:0、1、1、2、3、5、8、13、21、34、55、89、144、233 ...
この規則に従います。現在の値は、前の2つの値の合計です。では、n番目の値は何ですか?
まず、状態遷移方程式を簡単に取得できます。f(n)= f(n − 1)+ f(n − 2)、n> = 2 f(n)= f(n-1)+ f(n- 2)、n> = 2f (n )=f (n−1 )+f (n−2 )、n>>=2
1.単純な再帰(反例):
def fib(n):
if n < 2:
return n
else:
return fib(n-1) + fib(n-2)
print(fib(100))
時間計算量インデックスレベル、書き込み効果なしと同じ
2.動的計画法
def fib(n):
result = list(range(n+1)) # 缓存以往的结果,方便复用(目标2)
for i in range(n+1): # 按顺序从小往大算(目标3)
if i < 2:
result[i] = i
else:
# 使用状态转移方程(目标1),同时复用以往结果(目标2)
result[i] = result[i-1] + result[i-2]
return result[-1]
if __name__ == "__main__":
result = fib(100)
print(result)
2.異なるパス(難易度)
class Solution():
def uniquePaths(self, m, n): # 将二维列表初始化为1,以便之后用于缓存(目标2)
dp = [[1]*n]*m
for i in range(1, m): # 外循环逐行计算(目标3)
for j in range(1, n): # 内循环逐行计算(目标3)
dp[i][j] = dp[i][j-1] + dp[i-1][j] # 状态方程(目标1),以及中间结果复用(目标2)
return dp[m-1][n-1]
s = Solution()
m = 3
n = 2
print(s.uniquePaths(m, n))