洛谷P1216数字三角形 Number Triangles

Description

观察下面的数字金字塔。

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

在上面的样例中,从7→3→8→7→5 的路径产生了最大权值。

Input

第一个行一个正整数 r ,表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

Output

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

Sample 1

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

Hint

【数据范围】
对于 100%100% 的数据,1≤r≤1000,所有输入在 [0,100][0,100] 范围内。


思路

 题目要求从最高点到最低点的路径中权值最大的一条路径

我们既可以从上到下考虑,也可以从下到上考虑

如果从上到下考虑的话,要考虑是从左上下来还是右上下来,这时最右边的数据要进行特判,因为它没有右上数,所以我们从下到上考虑。

我们用二维数组来存储数据,则最大路径中(i,j)这个数由(i+1,j)或(i+1,j+1)中最大的那个相连,而这两个点又由它们下面最大的相连,也就是递归来求,设f(i,j)表示从底层到这个点的最大路径的和;w(i,j)表示这个点的数,那么f(i,j) = (i+1,j)和(i+1,j+1)中路径和大的那个 + w(i,j)

代码如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 1010;//大于1000即可

int f[N][N];//从最下方走到(i,j)的所有路线里的最大值
int w[N][N];//第i行第j列的数

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--)
    {
        for(int j = 1;j <= i;j++)
        {
            //第i行第j个的数的最大值就等于 从它左下和右下来的数据中的最大值加它本身
            f[i][j] = max(f[i+1][j],f[i+1][j+1]) + w[i][j];
        }
    }

    //从最下方走到(1,1)的所有路径的最大值
    cout << f[1][1] <<endl;
    return 0;
}

详细讲解:【寒假每日一题】Day-2(《898. 数字三角形》动态规划)_哔哩哔哩_bilibili

解法二:dp

#include<bits/stdc++.h>
using namespace std;

const int N = 1010;
int g[N][N];//存数
int f[N][N];//用f来表示状态
int r;

int main()
{
    cin >> r;
    //读入三角形
    for(int i = 1;i <= r;i++)
    {
        for(int j = 1;j <= i;j++)
        {
            cin >> g[i][j];
        }
    }

    //将三角形及周边点初始化为负无穷
    for(int i = 0;i <= r+1;i++)
    {
        for(int j = 0;j <= r+1;j++)
        {
            f[i][j] = -0x3f;
        }
    }

    //dp核心
    //每个点由它左上或右上来,左上即[i-1][j-1],右上即f[i-1][j],再加上它本身,两个中最大的就是最大值
    f[1][1] = g[1][1];
    for(int i = 2;i <= r;i++)
    {
        for(int j = 1;j <= r;j++)
        {
            f[i][j] = max(f[i-1][j-1]+g[i][j],f[i-1][j]+g[i][j]);
        }
    }

    //计算最后一行中最大的值
    int res = 0;
    for(int i = 1;i <= r;i++)
    {
        res = max(res,f[r][i]);
    }

    cout << res <<endl;
    return 0;
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值