動態規劃題目--數塔(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));
}
}
}