1. 程式人生 > >數塔(hdoj 2084,動態規劃遞推)

數塔(hdoj 2084,動態規劃遞推)

在講述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
//我這裡只考慮了一組資料,需要測試多組資料請自行更改
#include<bits/stdc++.h> #define
ll long long using namespace std; const ll maxn=101; ll a[maxn][maxn]; int main() { ll n;//n:幾層的塔 cin>>n; for(ll i=1;i<=n;i++) for(ll j=1;j<=i;j++) scanf("%lld",&a[i][j]); //向數塔輸入數字 // 如果從上往下看,這個問題就變得很複雜 // 但是如果自底向上遞推就能解決問題 // // 任何一個格子向下走的時候都有兩種方案,不知道選哪個可以獲得全域性最優解
// 那麼對於每兩個相鄰的格子,找出他們兩最大的值,然後賦值給他們上面的那個格子 // 1 // 3 4 // 1 3 7 // 1 6 4 5 // 5 7 6 7 4 // 對於左下角的5,7=>1 // 5和7中7最大,那麼1+7=8 // 就是說從元素較多的底下往上推,不用管選擇哪個的問題 // 每一次最好的結果都篩選出來了 for(ll i=n;i>=2;i--)//把i這行最好的賦給i-1,所以i要大於2而不是大於1 for(ll j=1;j<=i-1;j++)//列舉i這行每兩個相鄰配對,所以j<=i-1而不是j<=i
{ a[i-1][j]+=max(a[i][j],a[i][j+1]); } cout<<a[1][1]<<endl; // a[1][1]收集了a[2][1]和a[2][2]中最大一個 // 而a[2][1]又收集了a[3][1]和a[3][2]中最大一個...... }