1. 程式人生 > >動態規劃題目--數塔(HDU)

動態規劃題目--數塔(HDU)

因為之前沒有怎麼接觸過演算法,在賽碼網上刷題,碰上了動態規劃類的題目。正好藉此機會系統的學習一下。

在嗶哩嗶哩上看演算法視訊,裡面講解了一道HDU上的題目,下面貼下題目描述:

ime Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 36261    Accepted Submission(s): 21659


 

Problem Description

在講述DP演算法的時候,一個經典的例子就是數塔問題,它是這樣描述的:

有如下所示的數塔,要求從頂層走到底層,若每一步只能走到相鄰的結點,則經過的結點的數字之和最大是多少?


已經告訴你了,這是個DP的題目,你能AC嗎?

Input

輸入資料首先包括一個整數C,表示測試例項的個數,每個測試例項的第一行是一個整數N(1 <= N <= 100),表示數塔的高度,接下來用N行數字表示數塔,其中第i行有個i個整數,且所有的整數均在區間[0,99]內。

Output

對於每個測試例項,輸出可能得到的最大和,每個例項的輸出佔一行。

Sample Input

1

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

Sample Output

30

解題思路:在不瞭解動態規劃題目之前,應該首先想到的就是貪心吧,從頂想下,每次找最大的。經過測試,得到的結果為26。不如給出的樣例結果大,貪心演算法宣告失敗。

遞迴的思路比較好想:順著題目,我們從上往下看。第一層的節點沒有什麼好說的,他只有一個,但是到了第二層,節點就變成了兩個。這就遇到了一個“選還是不選“的問題。假如我們選了第一個節點,而不選第二個節點。問一下自己,為什麼不選第二個節點?當然是第一個節點的值大唄(注意了,上一段中我們已經說了,貪心的方法行不通,所以這裡的”值大“代表經過處理後的值,怎麼處理。。。下面講)。同樣的方法,繼續進行第3,4,···n-1層的選擇處理,到了第n層(遞迴的出口),選出較大的節點值,然後在進行回溯,就解決了。

經過遞迴思路的分析,注意到第n-1層依賴於第n層。所以我們只需將第n-1層各節點中子節點的最大值加上他們本身即可。如此向上處理。第一層的那個節點的值就是我們求的最大值。這裡用的是遞推的思想:從底向下分析。

程式碼:

import java.util.*;

public class Main {
    public static int dp_numberta(int[][] arr,int n){

        for(int i=n-2;i>=0;i--){
            for(int j=0;j<=i;j++){
                arr[i][j] = Math.max(arr[i+1][j],arr[i+1][j+1])+arr[i][j];
            }
        }
        return arr[0][0];
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for(int k = 0;k<n;k++){
            int N = sc.nextInt();
            int[][] arr = new int[N][N];
            for(int i=0;i<N;i++){
                for (int j=0;j<=i;j++){
                    arr[i][j] = sc.nextInt();
                }
            }
            System.out.println(dp_numberta(arr,N));
        }

    }
}