動態規劃 1 重疊子問題的性質

2021-08-27 16:55:54 字數 3071 閱讀 2854

動態規劃(dp)通過分解成子問題解決了給定複雜的問題,並儲存子問題的結果,以避免再次計算相同的結果。我們通過下面這個問題來說明這兩個重要屬性:

1)重疊子問題

2)最優子結構

1)重疊子問題:

像分而治之,動態規劃也把問題分解為子問題。動態規劃主要用於:當相同的子問題的解決方案被重複利用。在動態規劃中,子問題解決方案被儲存在乙個表中,以便這些不必重新計算。因此,如果這個問題是沒有共同的(重疊)子問題, 動態規劃是沒有用的。例如,二分查詢不具有共同的子問題。下面是乙個斐波那契函式的遞迴函式,有些子問題被呼叫了很多次。

1/* ****** recursive program for fibonacci numbers */

2intfib(intn)

3

執行 fib(5) 的遞迴樹

1fib(5)

2/             \

3fib(4)                fib(3)

4/      \                /     \

5fib(3)      fib(2)         fib(2)    fib(1)

6/     \        /    \       /    \

7fib(2)   fib(1)  fib(1) fib(0) fib(1) fib(0)

8/    \

9fib(1) fib(0)

我們可以看到,函式f(3)被稱執行2次。如果我們將儲存f(3)的值,然後避免再次計算的話,我們會重新使用舊的儲存值。有以下兩種不同的方式來儲存這些值,以便這些值可以被重複使用。

a)記憶化(自上而下):

b)打表(自下而上):

一)記憶化(自上而下):記憶化儲存其實是對遞迴程式小的修改,作為真正的dp程式的過渡。我們初始化乙個陣列中查詢所有初始值為零。每當我們需要解決乙個子問題,我們先來看看這個陣列(查詢表)是否有答案。如果預先計算的值是有那麼我們就返回該值,否則,我們計算該值並把結果在陣列(查詢表),以便它可以在以後重複使用。

下面是記憶化儲存程式:

01/* memoized version for nth fibonacci number */

02#include

03#define nil -1

04#define max 100

05

06intlookup[max];

07

08/* function to initialize nil values in lookup table */

09void_initialize()

10

15

16/* function for nth fibonacci number */

17intfib(intn)

18

26

27returnlookup[n];

28}

29

30intmain ()

31

一)打表(自下而上)

下面我們給出自下而上的打表方式,並返回表中的最後一項。

view source

01/* tabulated version */

02#include

03intfib(intn)

04

13

14intmain ()

15

這兩種方法都能儲存子問題解決方案。在第乙個版本中,記憶化儲存只在查詢表儲存需要的答案。而第二個版本,所有子問題都會被儲存到查詢表中,不管是否是必須的。比如lcs問題的記憶化儲存版本,並不會儲存不必要的子問題答案。

1277 統計全為 1 的正方形子矩陣(動態規劃)

1.問題描述 2.思路分析 一開始的時候對於也想到了應該會是動態規劃的思路來解決,但是沒有想到具體的解決方案,動態規劃的難點一般也是在這裡,在官方的題解中提供的思路是使用乙個二維的list列表來記錄中間的結果,dp i j 表示以當前的i,j位置的正方形的個數,能夠想到這個思路也是非常巧妙的,當是第...

動態規劃解不包含相同數字的子串個數問題

比賽描述 仙靈女巫露露,對於魔法的熱忱可是超出常人,要是發現了什麼上古遺留下的魔法,她總是想方設法地獲得,然後研究分析。而最近,他又從 小法師維嘉那裡獲得了乙個 奇怪 的魔法卷軸 這個魔法卷軸上有一大串數字,而且根據卷軸上的描述,這個魔法的威力指數來自於這一串數字中 魔法區間 的數量 所謂 魔法區間...

1003 求最大連續子串行和的動態規劃問題

解題思路 在最初看到題目的時候,因為動態規劃往往要存很多中間變數,因此想到陣列是最方便的。但是要注意的是,題目中的n數值非常大,如果都採用陣列來儲存的話,會出現記憶體不足的情況,因此可以考慮用其他的方法。在本題中,可以分析到,在每次讀入乙個新的資料時,都可以根據新讀入的資料和過去的一些記錄的比較,來...