演算法與資料結構 動態規劃

2021-09-22 05:52:40 字數 3061 閱讀 1905

用遞迴求解問題時,反覆的巢狀會浪費記憶體。而且更重要的一點是,之前計算的結果無法有效儲存,下一次碰到同乙個問題時還需要再計算一次。例如遞迴求解 fibonacci 數列,假設求第 n 位(從 1 開始)的值,c **如下:

#include

intfib

(int n)

return

fib(n -1)

+fib

(n -2)

;}intmain

(void

)

上面的**,每個運算節點都需要拆成兩步運算,時間複雜度位 o(2^n)。

你可以把 n 改為 40 左右試試,這是消耗的時間就是秒級了。總共的求解步驟如下:

求第 2 位

求第 3 位

如果想把每次求解的結果儲存下來,就需要乙個長度位 n 的陣列,從頭開始把每乙個位置的值儲存下來,這樣求解後面的值的時候就可以用了。

對於遞迴,只要寫好了退出條件,之後不停的呼叫自身即可,最終到達退出條件時,逐個退出函式。

動態規劃則是從頭開始,用迴圈達到目的。

動態規劃和遞迴的最大的區別,就是在碰到重疊子問題(overlap sub-problem)時,是否只需要計算一次。

#include

intfib

(int n)

return dp_opt[n -1]

;}intmain

(void

)

上面**的時間複雜的是 o(n)。

題目:從集合中,任取任意多個非相鄰的數字並求和,找出最大的和。例如,對於 ,最大的和是 14。

分析:對於任意第 n 位數字,都有兩種情況,只需要取值最大的那種即可:

遞迴退出條件:

遞迴迴圈:

int

recursive

(int arr,

int n,

int i)

為了確保每個最小子問題都只計算一次,就必須把計算的結果儲存起來。另外,跟遞迴的逆序求解方向相反,動態規劃從第乙個元素開始,依次計算每個元素的最大和:

int

dp_opt

(int arr,

int n,

int x)

opt[0]

= arr[0]

; opt[1]

= arr[0]

> arr[1]

? arr[0]

: arr[1]

;for

(i =

2; i < n; i++

)return opt[x]

;}

#include

// 遞迴解法

intrecursive

(int arr,

int n,

int i)

// 動態規劃

intdp_opt

(int arr,

int n,

int x)

opt[0]

= arr[0]

; opt[1]

= arr[0]

> arr[1]

? arr[0]

: arr[1]

;for

(i =

2; i < n; i++

)return opt[x];}

intmain()

;for

(i =

0; i <

7; i++

)return0;

}

例如,對於 ,給定值位 15,則可以找到組合 滿足條件。

要判斷多個元素之和是否等於某個值 sum,則對於任意的元素 n,情況如下:

遞迴退出條件:

遞迴迴圈:

int

recursive

(int arr,

int n,

int sum)

有了上面的遞迴的思路後,再把遞迴轉為動態規劃。

初始化二維陣列

上乙個例子中,求非相鄰元素最大和時,每個元素的位置上只需要儲存當前元素的最大值,所以建立乙個一維陣列即可。而現在已知元素之和,

例如,對於集合 ,如果 sum = 6,則需要建立 dp_subset[5][7] 陣列:

arr[i]

i \ sum01

2345

630f

fftf

ff50

t90t

10t2

0t開始迭代

在已經初始化的二維陣列基礎上,參考遞迴體就可以完成迭代的**。另外,還有乙個遞迴結束條件也放在迭代裡面。

int

dp_subset

(int arr,

int n,

#include

// 遞迴解法

intrecursive

(int arr,

int n,

int sum)

// 動態規劃

intdp_subset

(int arr,

int n,

int sum)

for(i =

0; i < n; i++

) subset[0]

[0]=

0;subset[0]

[arr[0]

]=1;

for(i =

1; i < n; i++

)else}}

return subset[n -1]

[sum];}

intmain()

;int sum =3;

printf

("recursive ret is: %d, dp_opt ret is: %d\n"

,recursive

(arr, n, sum)

,dp_subset

(arr, n, sum));

return0;

}

演算法與資料結構 動態規劃

動態規劃 dp 的基本思想是 當前子問題的解可由上一子問題的解得出。動態規劃演算法通常基於由乙個遞推公式 狀態轉移方程 和若干個初始狀態 狀態 應用 1 lis longest increasing subsequence 求乙個陣列中的最長非降子串行的長度。子問題 我們可以考慮先求a 0 a 1 ...

資料結構與演算法練習 動態規劃

hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0個開始,到第...

資料結構與演算法 156 159 動態規劃

揹包問題 有乙個揹包,容量為4磅,物品重量 吉他 g 11500 音響 s 43000 電腦 l 32000 動態規劃演算法介紹 動態規劃演算法最佳實踐 揹包問題 物品重量 吉他 g 11500 音響 s 43000 電腦 l 32000 思路和 v i 0 0 j 0 當 w i j時 v i j...