寒假每日一题 DP 数字三角形 2020-01-11

问题描述:

原题链接
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5

输入格式
第一行包含整数n,表示数字三角形的层数。

接下来n行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。

输出格式
输出一个整数,表示最大的路径数字和。

数据范围
1≤n≤500,
−10000≤三角形中的整数≤10000

输入样例:

5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

输出样例:

30

我的分析:

刚开始接触动态规划,个人觉得动态规划有点递归的味道,记住每个阶段的状态,下一次情况和上一次的状态有关,解决状态规划需要知道状态转化(状态计算,下一次和和上一次状态之间的联系)
典型问题:最大最长子序列,最大值问题。

解决方案:

这个题目可以用下往上找的方式,既可以不用考虑负数,也可以不用像顺推一样考虑边界带来种种裂开的问题。用f数组记录状态。

我的代码:

#include 
#include 
#include 
using namespace std;
const int N =510;
int a[N][N],f[N][N];
int n,m;
int main()
{
     
    cin>>n;
    for(int i=1;i<=n;++i){
     
        for(int j=1;j<=i;++j){
     
            cin>>a[i][j];
        }
    }
    //cout<<","<
    for(int i=1;i<=n;++i){
     
        f[n][i]=a[n][i];
    }
    //cout<<","<
    for(int i=n-1;i>=1;--i){
     
        for(int j=1;j<=i;++j){
     
            f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j];
        }
    }
    /*for(int i=1;i<=n;++i){
        for(int j=1;j<=i;++j){
            cout<
    cout<<f[1][1]<<endl;
    return 0;
}

第二种简略版只需要一个数组:

#include 
#include 
#include 
using namespace std;
const int N =510;
int f[N][N];
int n,m;
int main()
{
     
    cin>>n;
    //都从1开始,避免思路混乱,以后都这么用嘿嘿。
    for(int i=1;i<=n;++i){
     
        for(int j=1;j<=i;++j){
     
            cin>>f[i][j];
        }
    }
    for(int i=n-1;i>=1;--i){
     
        for(int j=1;j<=i;++j){
     //这个地方循环的结束要搞清楚,第i行有i个数
            f[i][j]+=max(f[i+1][j],f[i+1][j+1]);
        }
    }
    cout<<f[1][1]<<endl;
    return 0;
}

你可能感兴趣的:(算法,动态规划,数据结构)