[每日算法]数字三角形


题目描述

观察下面的数字金字塔。

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

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

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

输入格式

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

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

输出格式

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

输入输出样例

样例#1 输出#1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
30

说明/提示

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

题目翻译来自NOCOW。

USACO Training Section 1.5

IOI1994 Day1T1

题解

很明显这是个动态规划问题,如果用贪心求解那么只能得到局部最优解而不能得到全局最优解。 这个题目从上向下求解会比较麻烦,但是如果逆向求解即从下向上求解就很比较简单,状态转移方程为 f 【x】【y】=max(f【x+1】【y】,f【x+1】【y+1】)+a【x】【y】(f【i】【j】表示走到第i层第j个时的最大值)。最后输出a数组的最大值即可。

源代码

#include <iostream>
#include <cmath>
using namespace std;

int numberTriangles(int** nums, int n)
{
    int i, j;
    //从倒数第二排开始处理
    for (i = n - 2;i >= 0;i--)
    {
        for (j = 0;j <= i;j++)
        {
            nums[i][j] += max(nums[i + 1][j], nums[i + 1][j + 1]);
        }
    }
    return nums[0][0];
}

int main()
{
    int n, i, j, num;
    cin >> n;

    //动态开辟空间
    int** nums = new int* [n]; //开辟行
    for (i = 0; i < n; i++)
        nums[i] = new int[n]; //开辟列

    //将数据载入内存
    for (i = 0;i < n;i++)
    {
        for (j = 0;j <= i;j++)
        {
            cin >> num;
            nums[i][j] = num;
        }
    }

    //动态规划处理后输出结果
    cout << numberTriangles(nums, n);

    //释放开辟的资源
    for (i = 0; i < n; i++)
        delete[] nums[i];
    delete[] nums;

    return 0;
}

文章作者: 陈细利
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 陈细利 !
评论
 上一篇
[每日算法]滑雪 [每日算法]滑雪
题目描述Michael 喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的
2021-03-25
下一篇 
[每日算法]部分背包问题 [每日算法]部分背包问题
题目描述阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N(N≤100) 堆金币,第 i 堆金币的总重量和总价值分别是mi,vi(1≤mi,vi≤100)。阿里巴巴有一个承重量为T(T≤1000) 的背包,但并不一定有办法将全部的金币都装进去
2021-03-17
  目录