数字金字塔(dp)


链接:https://ac.nowcoder.com/acm/problem/22909
来源:牛客网

题目描述

考虑在下面被显示的数字金字塔。
写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大。
每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大和:30

输入描述:

第一个行包含 R(1<= R<=1000)
,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。

输出描述:

单独的一行包含那个可能得到的最大的和。
示例1

输入

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

输出

复制
30




DP的第一步,把状态设计出来。
本题可以这样设计状态:

f(x,y)表示:走到(x,y)位置,能获得的最大收益
接下来建立各状态的联系

要么从左上角走过来,要么从右上角走过来。所以我们可以得出核心公式:

f(x,y)=w(x,y)+max(f(x-1,y-1),f(x-1,y))


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include using namespace std; const int N=1010; int dp[N][N],w[N][N]; int main() {     int r;     cin>>r;     for(int i=1;i<=r;i++)     {         for(int j=1;j<=i;j++)         {             cin>>w[i][j];         }     }     for(int i=1;i<=r;i++)     {         for(int j=1;j<=i;j++)         {             dp[i][j]=w[i][j]+max(dp[i-1][j-1],dp[i-1][j]);         }     }     int ans=-1;     for(int i=1;i<=r;i++)     {         ans=max(ans,dp[r][i]);     }     cout<       return 0; }


for(int i=0;i<=r;i++)
    {
        for(int j=0;j<=i;j++)
        {
            dp[i+1][j]=max(dp[i+1][j],dp[i][j]+w[i+1][j]);
            dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]+w[i+1][j+1]);
        }
    }

  我们还可以正着写。(用数去更新)