1. 程式人生 > >動態規劃——數字三角形

動態規劃——數字三角形

-- 就是 程序 else 視頻 問題: 維數 技術 i+1

題目: (題目來源:中國大學Mooc,程序設計與算法(二)算法基礎視頻課程)

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或右下走。只需要求出這個最大和即可,不必給出具體路徑。(三角形的行數大於1小於等於100,數字為0-99)

解題思路:

用二維數組存放數字三角形。

D(r,j):第r行第j個數字(r,j從1開始算)

MaxSum(r,j):從D(r,j)到底邊的各條路徑中,最佳路徑的數字之和。

問題:求MaxSum(1,1)

典型的遞歸問題。D(r,j)出發,下一步只能走D(r+1,j)或者D(r+1,j+1)。故對於N行的三角形:

if(r==N)

MaxSum(r,j) = D(r,j)

else

MaxSum(r,j) = Max { MaxSum(r+1,j) , MaxSum(r+1 , j+1) } + D(r,j)

遞歸代碼:

#include "stdafx.h"
#include <iostream>
#include <algorithm>

#define MAX 101
using namespace std;

int D[MAX][MAX];
int n;

int MaxSum(int i,int j)
{
    if(i==n)
        
return D[i][j]; int x = MaxSum(i+1,j); int y = MaxSum(i+1,j+1); return max(x,y)+D[i][j]; } int _tmain(int argc, _TCHAR* argv[]) { int i,j; 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; }

記憶型遞歸代碼:

#include "stdafx.h"
#include <iostream>
#include <algorithm>

#define MAX 101
using namespace std;

int D[MAX][MAX];
int maxSum[MAX][MAX];
int n;

int MaxSum(int i,int j)
{
    if(maxSum[i][j]!=-1)
        return maxSum[i][j];
    if(i==n)
        return D[i][j];
    int x = MaxSum(i+1,j);
    int y = MaxSum(i+1,j+1);
    return max(x,y)+D[i][j];
}

int _tmain(int argc, _TCHAR* argv[])
{
    int i,j;
    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;
}

將遞歸轉化為遞推:

比如

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

從最下面一層 4 5 2 6 5開始往上面推,比如:max(4,5)+2=7,用新得到的7存放到原來2的位置,這樣反復循環往上計算,最終得到30。

因此規律就是:maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j]。

30

23 21

20 13 10

7 12 10 10

4 5 2 6 5

遞推代碼:

#include "stdafx.h"
#include <iostream>
#include <algorithm>

using namespace std;

#define MAX 101
int D[MAX][MAX];
int n;
int maxSum[MAX][MAX];

int _tmain(int argc, _TCHAR* argv[])
{
    int i,j;
    cin>>n;

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

    for(int i =1 ;i<=n;++i)
    {
        maxSum[n][i] = D[n][i];
    }

    for(int i = n-1;i>=1;--i)
    {
        for(int j=1;j<=i;++j)
        {
            maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1])+D[i][j];
        }
    }
    cout << maxSum[1][1]<<endl;

    return 0;
}

運行結果示例:

技術分享圖片

動態規劃——數字三角形