動態規劃 數字三角形問題

2021-08-30 21:46:41 字數 2022 閱讀 6638

有乙個由非負整數組成的三角形,第一行只有乙個數,除了最下行之外每個數的左下方和右下方各有乙個數.

3 24 10 1

4 3 2 20

從第一行的數開始,每次可以往左下或右下走一格,直到走到最下行,把沿途經過的數全部加起來,如何走才能使得這個和盡量大?

輸入:三角形的行數n,數字三角形的各個數(從上到下,從左到右)

輸出:最大的和。

執行結果:

如果熟悉回溯法,可能會立刻發現這是乙個動態的決策問題:每次有兩種選擇-左下或右下。如果用回溯法求出所有可能的路線,就可以從中選出最優路線。但和往常一樣,回溯法的效率太低;乙個n層數字三角形的完整路線有

為了得到高效的演算法,需要用抽象的方法思考問題:把當前的位置(i,j)看成乙個狀態(還記得麼?)然後定義狀態(i,j)的指標函式d(i,j)為從格仔(i,j)出發時能得到的最大和(包括格仔(i,j)本身的值)。在這個狀態定義下,原問題的解是d(1,1)

下面看看不同狀態之間是如何轉移的。從格仔(i,j)出發有兩種決策。如果往左走,則走到(i+1,j)後需要求「從(i+1,j)」出發後能得到的最大和「這一問題,即d(i+1,j)。類似得,往右走之後需要求解d(i+1,j+1)。由於可以在這兩個決策中自由選擇,所以應選擇d(i+1,j)和d(i+1,j+1)中較大的乙個,換句話說,得到了所謂的狀態轉移方程:

d(i,j) = a(i,j) + max

如果往左走,那麼最好情況等於(i,j)格仔裡的值a(i,j)與」從(i+1,j)出發的最大總和「之和,此時需注意這裡的最大二字。如果連」從(i+1,j)出發走到底部「這部分的和都不是最大的,加上a(i,j)之後肯定也不是最大的。這個性質稱為最優子結構,也可以描述成全域性最優解包含區域性最優解。不管怎樣,狀態和狀態轉移方程一起完整的描述了具體的演算法。

int a[100][100],n,d[100][100];
第一種方法是遞迴計算(需注意邊界處理)。

int solve1(int i,int j)

*/ return a[i][j]+(i==n? 0 : max(solve1(i+1,j),solve1(i+1,j+1)));

}

這樣做是正確的,但時間效率太低,其原因在於重複計算。在solve(1,1)對應的呼叫關係樹中,solve(3,2)被計算了兩次(一次是solve(2,1)需要的,一次是solve(2,2)需要的)。也許讀者會認為重複算一兩個數沒有太大影響,但事實是:這樣的重複不是單個結點,而是一顆子樹。如果原來的三角形有n層,則呼叫關係樹也會有n層,一共有遞推計算(需再次注意邊界處理):

int solve2()

程式的時間複雜度顯然是可以用遞推法計算狀態轉移方程。遞推的關鍵是邊界和計算順序。在多數情況下,遞推法的時間複雜度是:狀態總數 * 每個狀態的決策個數 * 決策時間。如果不同狀態的決策個數不同,需具體問題具體分析。

記憶化搜尋。程式分成兩部分。首先用 memset(d,-1,sizeof(d)); 把d全部初始化為-1,然後編寫遞迴函式。

int solve3(int i,int j)

上述程式仍然是遞迴的,但同時也把計算結果儲存在陣列d中。題目中所各個數都是非負的,因此如果已經計算過某個d[i][j],則它應是非負的。這樣,只需把所有d初始化為-1,即可通過判斷是否d[i][j]>=0得知它是否已經被計算過。

最後,千萬不要忘記把計算之後把它儲存在d[i][j]中,根據c語言 賦值語句本身有返回值的規定,可以把儲存d[i][j]的工作合併到函式的返回語句中。

上述程式的方法稱為記憶化,它雖然不像遞推法那樣顯式地指明了計算順序,然仍然可以保證每個結點只訪問一次。

由於i和j都在1-n之間,所有不相同的結點一共只有

動態規劃 數字三角形問題

數字三角形問題 time limit 1000ms memory limit 65536kb problem description 給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。對於給定的由n行數字組成的數字三角形,計...

動態規劃 數字三角形問題

problem description 給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。對於給定的由n行數字組成的數字三角形,計算從三角形的頂至底的路徑經過的數字和的最大值。input 輸入資料的第1行是數字三角形的行數n...

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

description 下圖給出了乙個數字三角形,請編寫乙個程式,計算從頂至底的某處的一條路徑,使該路徑所經過的數字和最大 input 有很多個測試案例,對於每乙個測試案例,通過鍵盤逐行輸入,第1行是輸入整數 如果該整數是0,就表示結束,不需要再處理 表示三角形行數n,然後是n行數 output 輸...