動態規劃入門 數字三角形(從樸素遞迴到各種優化)

2022-06-04 15:09:07 字數 3527 閱讀 3695

數字三角形(poj1163)

description

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得

路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或

右下走。只需要求出這個最大和即可,不必給出具體路徑。

三角形的行數大於1小於等於100,數字為 0 - 99

輸入格式:

5 //三角形行數。下面是三角形

73 8

8 1 0

2 7 4 4

4 5 2 6 5

要求輸出最大和

sample output

30
source

ioi 1994

解題思路:

用二維陣列存放數字三角形。

d( r, j) : 第r行第 j 個數字(r,j從1開始算)

maxsum(r, j) : 從d(r,j)到底邊的各條路徑中,

最佳路徑的數字之和。

問題:求 maxsum(1,1)

典型的遞迴問題。

d(r, j)出發,下一步只能走d(r+1,j)或者d(r+1, j+1)。故對於n行的三角形:

if ( r == n)

maxsum(r,j) = d(r,j)

else

maxsum( r, j) = max + d(r,j)

改進如果每算出乙個maxsum(r,j)就儲存起來,下次用

到其值的時候直接取用,則可免去重複計算。

遞迴轉成遞推

「人人為我」遞推型動歸 pascal**

1 //by lyltim

2 3uses math;

4var

n,i,j:byte;

5 a:array[1..10,1..10]of

word;

6 f:array[1..10,1..10]of

word;

7begin

8 assign(input,'

tower.in

');reset(input);

9 assign(output,'

tower.out

');rewrite(output);

10readln(n);

11for i:=1

to n do

12begin

13for j:=1

to i do

14read(a[i,j]);

15readln;

16end

;17 fillchar(f,sizeof(f),0

);18

for i:=1

to n do f[n,i]:=a[n,i];

19for i:=n-1

downto1do

20for j:=1

to i do

21 f[i,j]:=max(f[i+1,j],f[i+1,j+1])+a[i,j];

22 writeln('

max=

',f[1,1

]);23

close(input);close(output);

24end.

空間優化

沒必要用二維maxsum陣列儲存每乙個maxsum(r,j),只要從底層一行行向上

遞推,那麼只要一維陣列maxsum[100]即可,即只要儲存一行的maxsum值就

可以。進一步考慮,連maxsum陣列都可以不要,直接用d的

第n行替代maxsum即可。

節省空間,時間複雜度不變

遞推+空間優化 c++**

1

//by lyltim2//

2015.2.11

3 #include 4 #include 5

using

namespace

std;

6int

main()

7

遞迴到動規的一般轉化方法

遞迴函式有n個引數,就定義乙個n維的陣列,陣列

的下標是遞迴函式引數的取值範圍,陣列元素的值

是遞迴函式的返回值,這樣就可以從邊界值開始,

逐步填充陣列,相當於計算遞迴函式值的逆過程。

動規解題的一般思路

1. 將原問題分解為子問題

 把原問題分解為若干個子問題,子問題和原問題形式相同

或類似,只不過規模變小了。子問題都解決,原問題即解

決(數字三角形例)。

 子問題的解一旦求出就會被儲存,所以每個子問題只需求

解一次。

2. 確定狀態

 在用動態規劃解題時,我們往往將和子問題相

關的各個變數的一組取值,稱之為乙個「狀

態」。乙個「狀態」對應於乙個或多個子問題,

所謂某個「狀態」下的「值」,就是這個「狀

態」所對應的子問題的解。

所有「狀態」的集合,構成問題的「狀態空間」。「狀態

空間」的大小,與用動態規劃解決問題的時間複雜度直接相關。

在數字三角形的例子裡,一共有n×(n+1)/2個數字,所以這個

問題的狀態空間裡一共就有n×(n+1)/2個狀態。

整個問題的時間複雜度是狀態數目乘以計算每個狀態所需

時間。在數字三角形裡每個「狀態」只需要經過一次,且在每個

狀態上作計算所花的時間都是和n無關的常數。

用動態規劃解題,經常碰到的情況是,k個整型變數能

構成乙個狀態(如數字三角形中的行號和列號這兩個變數

構成「狀態」)。如果這k個整型變數的取值範圍分別是

n1, n2, ……nk,那麼,我們就可以用乙個k維的陣列

array[n1] [n2]……[nk]來儲存各個狀態的「值」。這個

「值」未必就是乙個整數或浮點數,可能是需要乙個結構

才能表示的,那麼array就可以是乙個結構陣列。乙個

「狀態」下的「值」通常會是乙個或多個子問題的解。

3. 確定一些初始狀態(邊界狀態)的值

以「數字三角形」為例,初始狀態就是底邊數字,值

就是底邊數字值。

4. 確定狀態轉移方程

定義出什麼是「狀態」,以及在該 「狀態」下的「值」後,就要

找出不同的狀態之間如何遷移――即如何從乙個或多個「值」已知的

「狀態」,求出另乙個「狀態」的「值」(「人人為我」遞推型)。狀

態的遷移可以用遞推公式表示,此遞推公式也可被稱作「狀態轉移方

程」。能用動規解決的問題的特點

1) 問題具有最優子結構性質。如果問題的最優解所包含的

子問題的解也是最優的,我們就稱該問題具有最優子結

構性質。

2) 無後效性。當前的若干個狀態值一旦確定,則此後過程

的演變就只和這若干個狀態的值有關,和之前是採取哪

種手段或經過哪條路徑演變到當前的這若干個狀態,沒

有關係。

動態規劃入門 數字三角形

給定乙個由n行數字組成的數字三角形,如下圖所示 從上到下最大的值的總和。這道題在動態規劃裡是入門級的題目,運用到了遞迴。對於這道題共有兩個思路,第一種是從上向下推,第二種是從下向上推。先從第一種分析。我們設這個二維陣列為dp,在推導的時候我們先把遞的公式寫出來,從上向下退的話,zui a i j m...

數字三角形(動態規劃入門題)

題目描述 7 3 88 1 0 2 7 4 4 4 5 2 6 5 圖1 圖1給出了乙個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到乙個和,你的任務就是找到最大的和。輸入的是一行是乙個整數n 1 n 100 給出三角形的行數。下面的n行給出數字三角形...

動態規劃入門1 數字三角形 C

作為乙個菜雞,研究了幾天的dp,把經典例題研究了幾遍,現在,我在這發表一下自己的菜雞見解,記錄下我對dp的理解。dp裡面少不了遞迴,當然也能混在搜尋裡面構成記憶化搜尋作為優化,也可以用遞推來動態規劃。具體你要我說動態規劃是個什麼東西,我也只能說說自己的理解 滿足條件 綜上,這個動態規劃很重要的就是記...