Loading

动态规划——数字三角形

题目:  

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;
}

 进一步的,直接用一维数组存放每次计算后得到的值,得到简化后的递推代码如下:

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

using namespace std;

#define MAX 101
int D[MAX][MAX];
int n;
int maxSum[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[i] = D[n][i];
    }

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

    return 0;
}

 

运行结果示例:

 

posted @ 2017-12-18 15:04  guwei4037  阅读(468)  评论(0编辑  收藏  举报