数字三角形

一个很经典的题目了,以前没有学过dp感觉写的不明所以然,现在我觉得懂了吧...

闫式分析法我觉得我用的很奇怪,具体奇怪在哪我也说不上来,但我自己习惯于一种思考方式:

先上题目吧:

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

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

输入格式

第一行包含整数 nn,表示数字三角形的层数。

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

输出格式

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

数据范围

1n5001≤n≤500,
1000010000−10000≤三角形中的整数≤10000

输入样例:

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

输出样例:

30
这题一看就知道是dp题,不过做题目不能硬做,要分析了之后再写
比如在考虑状态转移方程的时候,从上到下考虑还是从下往上考虑,从上往下考虑的时候边界还要特判,很麻烦,所以优先考虑从下到上的顺序
对于我自己来说,首先是确立状态转移方程,就是令dp【i】或者dp【i】【j】代表了什么含义
比如这个题的f[i][j]代表了路径的最优解也就是最大值,之前的过河卒的dp[i][j]代表了到i,j这个点路径之和,还有昨天存钱的问题dp[i]代表了存到某个数的次数
背包问题那就更是经典。我说的这些好像就是y总说的集合的概念??
然后开始写状态转移方程了,这个就有很多种情况了,有类似于递推的过程,有类似于背包的一些问题
比如对应刚刚的问题,dp【i】【j】可以从左下和右下得到,然后每次得到时求最大值,过河卒就是感觉直接的递推了,每个坐标都由左和上得到,一共是x+y
存钱问题这个就好经典啊,dp[i]可以由dp[i-1]得到,可以由一个数加上6的次方之后得到,可以由一个数加上9的次方数得到。这些状态转移方程不就有了么
写的时候思路不是太清楚,谅解啊
#include<iostream>
using namespace std;
const int N=510;
int f[N][N],w[N][N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>w[i][j];
        }
    }
    for(int i=1;i<=n;i++) f[n][i]=w[n][i];//初始化
    for(int i=n-1;i>0;i--)//最后一行赋初值了,为最后一行的最大值,此时从n-1行开始 
    {
        for(int j=1;j<=i;j++)
        {
            f[i][j]=max(f[i+1][j]+w[i][j],f[i+1][j+1]+w[i][j]);
        } 
    } 
    cout<<f[1][1]<<endl;
    return 0;
}

就根据这道题咱们来分析一下:

首先令dp[i][j]为到达(i,j)这个坐标的最大值,类似于递推吧,然后从下到上递推(i,j)这个点可以由(i+1,j)和(i+1,j+1)两个点得到。然后类似的...我觉得分析到这边已经可以了...

加油吧!

posted @ 2022-02-13 18:11  小志61314  阅读(168)  评论(0)    收藏  举报