上面給出了乙個數字三角形。從三角形的頂部到底部有多條不同的路徑。對於每條路徑,把路徑上面的數字加起來可以得到乙個和,累加和最大的路徑成為「最佳路徑」。題目的任務就是求出最佳路徑上的數字之和。
注意:路徑上的每一步只能從乙個數走到下一層和它最近的左邊數或者右邊數。
第一行是乙個整數n,給出三角形的行數。下面的n行給出數字三角形。數字三角形中的數的範圍都在0~100之間。
輸出最大的和。
573
8810
2744
4526
5
#include
#include
#define max 101
using namespace std;
int d[max]
[max]
;int n;
intmaxsum
(int i,
int j)
intmain()
這道題如果用普通的遞迴來做,可以做出來,但時間複雜度很大,因為中間有很多重複計算,所以效率很低,如果算乙個100行的數字三角形,那這個算出這個結果的時間將是不可估量的。
但可以考慮記憶化遞迴來避免重複計算。
每算出乙個maxsum(r,j)就儲存起來,下次用到其值的時候直接取用,這樣可免去重複計算。那麼可以用o(n^2)時間完成計算。因為三角形的數字總 數是 n(n+1)/2
#include
#include
using namespace std;
#define max 101
int d[max]
[max]
;int n;
int maxsum[max]
[max]
;int
maxsum
(int i,
int j)
return maxsum[i]
[j];
}int
main()
cout <<
maxsum(1
,1)<< endl;
return0;
}
"動態規劃"是將乙個問題分解為子問題遞迴求解,並且將中間結果儲存以避免重複計算的方法。
而遞迴的思想在程式設計時未必要實現為遞迴函式,可以用遞推的方法來解決。從maxsum[n-1]這一行元素開始向上逐行遞推,最終得到maxsum[0][0]的值,即為最大值。
#include
#include
using namespace std;
#define m 100
int d[m]
[m];
int maxsum[m]
[m];
intmain()
}for
(int i=
0;i)for
(int i=n-
1;i>0;
--i)
} cout<
[0]<
return0;
}
還可以再進一步對空間做優化,在用遞推求解過程中,maxsum[i][j]的值在用來計算出maxsum[i-1][j]的值後已經無用,所以可以將計算出的maxsum[i-1][j]的值直接存放在maxsum[i][j]的位置。這樣maxsum不需要是二維陣列,一維陣列就足夠了。
#include
#include
using namespace std;
#define m 100
int d[m]
[m];
int*summax;
intmain()
} summax=d[n-1]
;//summax指向最後一行
for(
int i=n-
2;i>=
0;i--)}
cout<
<
return0;
}
但時間複雜度仍然是o(n^2)。 動態規劃 數字三角形
如圖所示的數字三角形,從頂部出發,在每一結點可以選擇向左走或得向右走,一直走到底層,要求找出一條路徑,使路徑上的值最大。第一行是數塔層數n 1 n 100 第二行起,按數塔圖形,有乙個或多個的整數,表示該層節點的值,共有n行。輸出最大值。5 1311 8 12 7 26 6 14 15 8 12 7...
動態規劃 數字三角形
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得 路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或 右下走。只需要求出這個最大和即可,不必給出具體路徑。三角形的行數大於1小於等於100,數字為 0 99 5 三角形行數。下面是三...
動態規劃 數字三角形
在用動態規劃解題時,我們往往將和子問題相關的各個變數的一組取值,稱之為乙個 狀態 乙個 狀態 對應於乙個或多個子問題,所謂某個 狀態 下的 值 就是這個 狀態 所對應的子問題的解。以 數字三角形 為例,初始狀態就是底邊數字,值就是底邊數字值。定義出什麼是 狀態 以及在該 狀態 下的 值 後,就要找出...