• 动态规划——数字三角形


    题目:  

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

    运行结果示例:

  • 相关阅读:
    (14) go 结构体
    (13) go map
    (12) go make初始化
    (11)go 数组和切片
    (10) go 错误
    (9) go 时间日期
    (8)go 字符串
    (7) go 函数
    (6) go 流程控制
    (5) go 格式化输入输出 类型转换
  • 原文地址:https://www.cnblogs.com/guwei4037/p/8057675.html
Copyright © 2020-2023  润新知