【9901】数塔问题

Time Limit: 10 second
Memory Limit: 2 MB

问题描述
设有一个三角形的数塔,顶点结点称为根结点,每个结点有一个整数数值。从顶点出发,在每一个结点可以选择向左走或者向右走一直走到底层,要求找出一条路径,使路径上的值最大。

Input

第一行有数塔层数n,接下来若干行为数塔。

Output

输出一行数据,即路径的最大值(包括一个换行符)

Sample Input

5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11

Sample Output

max=86

Sample Input2

10
1
121 18
12 72 26
63 14 15 8
125 57 13 24 11
11 12 63 58 47 45
0 152 365 12 36 59 987
0 1 23 4 5 6 7 8
25 36 99 87 44 51 23 69 65
10 12 35 92 15 2654 21 30 25 69

Sample Output2

max=3401

【题解】

这题是动态规划。先看一下数塔的样子如下

如果只有前两行,我们可以很快的得出来答案是24.

如果又加了一行。则我们不能肯定就是从13->11->12了。

我们在右边也要看一下。因为可能出现一个变态的数字让右边的路径也能更优。

于是我们开一个f[i][j]数组,f[2][1] = 24 f[2][2] = 21;

这样我们就记录了走到第二行第1个数字的最优解,和走到第二行第二个数字的最优解。

然后我们看第三行,可以看到12只能由2,1走到。那么f[3][1] = f[2][1]+a[3][1],a[3][1] = 12;

然后是第三行的第二个数字7,7可以由11 和 8走到,于是我们就判断一下f[2][1]和f[2][3] 它们分别加上a[3][2]后哪一个会比较大。然后把它赋值给f[3][2]。

然后是第三行的第三个数字26,26只能由8走到。于是f[3][3] = f[2][2] + a[3][3];

这样我们就求出了到达第3行第j列的所有位置的最优解。依照我们处理第三行的规律。

我们可以得出第四行的最优解。

由此得出动态转移方程

f[i][j] = max(f[i-1][j-1],f[i-1][j]);

【代码】

#include <cstdio>
#include <stdlib.h>

int n,a[100][100],f[100][100],ans;

void input_data()
{
    scanf("%d",&n);
    for (int i = 1;i <= n;i++)
        for (int j = 1;j <=i;j++) //读入数字矩阵
            scanf("%d",&a[i][j]);
}

int ma_x(int x,int y) //获取x和y中的更大值、
{
    if (x > y)
        return x;
            else
                return y;
}

void get_ans()
{
    f[1][1] = a[1][1]; //第一排的第一个数字用于作为动规的奠基
    for (int i = 2;i <= n;i++)
        for (int j = 1;j <=i;j++) //然后根据状态转移方程求出下面的f[i][j]
            f[i][j] = ma_x(f[i-1][j-1]+a[i][j],f[i-1][j]+a[i][j]);
    ans = f[n][1];
    for (int i = 2;i <= n;i++) //在最后一层中找答案(最大值)
        ans = ma_x(ans,f[n][i]);
}

void output_ans()
{
    printf("max=%d\n",ans);
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    input_data();
    get_ans();
    output_ans();
    return 0;
}


 

 

posted @ 2017-10-06 19:23  AWCXV  阅读(235)  评论(0编辑  收藏  举报