[动态规划]数字三角形 Number Triangles

303 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

[USACO1.5][IOI1994]数字三角形 Number Triangles

题目描述

观察下面的数字金字塔。

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

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

在上面的样例中,从 738757 \to 3 \to 8 \to 7 \to 5 的路径产生了最大

输入格式

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

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

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

30

提示

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

题目翻译来自NOCOW。

USACO Training Section 1.5 IOI1994 Day1T1

解题思路

不妨把问题变为求“从底部任意点走到最高点的路径”的最大数字和。

我们令a[i][j]表示第i行第j列上的数。

设f[i][j]表示从底端走到第i行第j列时的最大路径和,那么它的值就是f[i+1,j]和f[i+1,j+1]两者的较大值加上a[i][j] 。

状态转移方程为f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j]

边界f[R][i]=a[R][i]

最后的答案即为f[1][1]。

#include<stdio.h>
int a[1001][1001],d[1001][1001];
int main(void)
{
    int n,i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=i;j++)
            scanf("%d",&a[i][j]);
    for(i=1;i<=n;i++) d[n][i]=a[n][i];//最底层的点
    for(i=n-1;i>=1;i--)
        for(j=1;j<=i;j++)
            d[i][j]=d[i+1][j]>d[i+1][j+1]? d[i+1][j]+a[i][j] :d[i+1][j+1]+a[i][j];
    printf("%d",d[1][1]);
    return 0;
}