1. 題目介紹
上圖給出了一個數字三角形。
從三角形的頂部到底部有很多條不同的路徑。
對於每條路徑,把路徑上面的數加起來可以得到一個和,你的任務就是找到最大的和。
路徑上的每一步只能從一個數走到下一層和它最近的左邊的那個數或者右邊的那個數。
輸入格式
輸入的第一行包含一個整數 N,表示三角形的行數。
下面的 N 行給出數字三角形。
數字三角形上的數都是 0 至 100 之間的整數。
輸出格式
輸出一個整數,表示答案。
輸入樣例
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
輸出樣例
27
資料範圍
1 ≤ N ≤ 100
2. 題解
2.1 遞推(逆向)/ 動態規劃
思路
由於我們正向列舉的話,第一個和下方兩個相加產生兩種情況,第二個和下方兩個相加又是兩種,最後會產生 \(2^n\) 種情況,導致超時
這裡使用逆向遞推的思路,我讓下方兩個中較大的那個去加上他們的父節點,這樣時間複雜度由\(O(2^n)\)降低為\(O(n^2)\),極大簡化了過程。
這裡其實也可以看作是動態規劃的觀點,雖然直接更新了arr,如果看作是dp的話,那麼arr[i][j] 就是代表第i行第j列所能得到的最大值!
程式碼
#include<bits/stdc++.h>
using namespace std;
int n;
int arr[101][101];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) {
cin >> arr[i][j];
}
}
for(int i = n - 1; i >= 1; i--) {
for(int j = 1; j <= i; j++) {
arr[i][j] += max(arr[i+1][j], arr[i+1][j+1]);
}
}
cout << arr[1][1];
return 0;
}