一.實踐題目
數字三角形
給定一個由 n行數字組成的數字三角形如下圖所示。試設計一個算法,計算出從三角形 的頂至底的一條路徑(每一步可沿左斜線向下或右斜線向下),使該路徑經過的數字總和最大。
輸入格式:
輸入有n+1行:
第 1 行是數字三角形的行數 n,1<=n<=100。
接下來 n行是數字三角形各行中的數字。所有數字在0..99 之間。
輸出格式:
輸出最大路徑的值。
輸入樣例:
在這里給出一組輸入。例如:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
輸出樣例:
在這里給出相應的輸出。例如:30
二.問題描述
輸入數字三角形,從三角形頂點開始,每次只能在左右兩邊選擇路徑,每經過一個點取得該點數值,設計算法,求出和的最大的值。
三.算法描述
使用自底向上遞推的方式,在每一行比較改行所有子問題的最優解,繼續往上計算,知道頂點,則比較出的則為最優解。
#include <iostream> #define Max 101 using namespace std; int n; int a[Max][Max]; //用來存儲數字三角形的二維數組 int MaxSum[Max][Max];//用來存儲第i行第j列到底邊的最大值 int main(){ //輸入數字三角形 cin >> n; for(int i=1;i<=n;++i) for(int j= 1;j<=i;++j) cin >> a[i][j]; for(int i=1;i<=n;++i) MaxSum[n][i] = a[n][i]; for(int i=n-1;i>=1;--i) //自底向上計算 for(int j = 1;j<=n;++j) MaxSum[i][j] = (MaxSum[i+1][j] > MaxSum[i+1][j+1] ? MaxSum[i+1][j] : MaxSum[i+1][j+1]) + a[i][j]; cout << MaxSum[1][1]; return 0; }
四.算法時間及空間復雜度分析
若采用遞歸算法,則時間復雜度為0(2^n),使用遞歸加備忘錄的方法,雖減少了對重復子問題的計算,但進棧出棧的時間、避免了棧溢出等問題仍沒有解決,動態規划算法使用雙重循環自底向上計算最優解,所以時間復雜度為O(n^2),
但新增二維數組保存每個子問題的解,空間復雜度為0(n^2)。五.心得體會
1.與遞歸方法比,動態規划算法時間復雜度較低,且沒有棧溢出的風險,備忘錄方法雖解決了子問題重復計算的問題,但仍然有棧溢出風險。
2.遞歸方法、遞歸備忘錄方法都是自頂向下的算法,而動態規划算法是自頂向下的迭代算法,子問題只計算一次。
3.動態規划算法是用空間代價換取時間代價的算法。