1. 程式人生 > >【動態規劃】數字三角形最大值(一)(遞迴)

【動態規劃】數字三角形最大值(一)(遞迴)

題目:數字三角形,形如

         3

     3      2

  4     5     1

1    3     4     1

每個點只能選擇向左或向右走,取一條路徑,使得路徑上數字和最大。

無需求出路徑,求出最大值。

輸入n,和 n 行數字三角形 n<=100

思路:遞迴解決

用二維陣列 d[ l ][ r ] 存數字三角形

 if ( l  ==  n) maxSum( l , r ) = d [ l ][ r ] ;

 else maxSum ( l , r ) = max { maxSum( l+1, r ) , maxSum( l+1, r+1 ) }

很簡單呀

程式碼如下:

#include <iostream>
#include <algorithm>

using namespace std;

#define MAX 101

int d[MAX][MAX];
int n;

int MaxSum(int l,int r)
{

    if(l==n)
        return d[l][r];
    else
        return max(MaxSum(l+1,r),MaxSum(l+1,r+1))+d[l][r];

}

int main()
{

    cin >> n;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
            cin >> d[i][j];
    cout << MaxSum(1,1) << endl;

    return 0;

}

好了,資料量大一點的時候,就華麗麗的超時了

分析一下時間複雜度,發現是 O(2^n),原因是

會 重 復 計 算 maxSum (r,l) 的值!

————————————————————————————————————————————————————————————————————————————

優化:(記憶遞迴型動態規劃)

思路:那就把計算結果存下來嘛。

程式碼如下:

#include <iostream>
#include <algorithm>

using namespace std;

#define MAX 101

int d[MAX][MAX];
int n;
int maxSum[MAX][MAX];

int MaxSum(int i,int j)
{
    if(maxSum[i][j]!=-1)
        return maxSum[i][j];
    if(i==n)
        maxSum[i][j] = d[i][j];
    else
        maxSum[i][j] = max(MaxSum(i+1,j),MaxSum(i+1,j+1)) + d[i][j];

    return maxSum[i][j];
}


int main()
{

    cin >> n;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++){
            cin >> d[i][j];
            maxSum[i][j]=-1;
        }

    cout << MaxSum(1,1) << endl;

    return 0;
}

演算法時間複雜度成功變成 O(n^2);

不過遞迴還是慢一點,繼續優化!