数字和最大(读入外挂模板+DP或滚动数组)

本文介绍了一种使用读入外挂解决最大路径和问题的方法,并提供了两种解题思路。第一种是经典的自底向上动态规划,通过模板实现整数读入;第二种则是进一步优化的解法,利用了前缀最大值的思想。文章详细解释了两种方法的实现过程,并通过样例输入输出展示了具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem C

Time Limit:1000MS  Memory Limit:65536K
Total Submit:58 Accepted:13

Description

一日,code4101捡到一本《读入外挂》的武林秘籍。书上说,用getchar一个字符一个字符来手动实现整数的读入,比scanf直接读取一个整数要快上好多倍。 
code4101怀疑有没有这么神奇,就想用读入外挂试试这道熟悉的题目,来一起AC吧。 
考虑下图这个三角形,从第一行走到最后行,每一步都只能往下一行相邻的左边或右边移动,如何使路过的数字和最大。 
 

如上面这个例子,行走路线:7->3->8->7->5,是和最大的走法,为30。 

Input

输入数据的第一行为一个整数T,表示有T(0 < T < 5)组测试数据。 
每个测试的第一行是一个整数R (1 <= R <= 3000),代表行数,接下来R行,第i行有i个正整数代表三角形每行的数值。 
所有的单个元素值,及最终的和,均小于2 * 10^18。 

Output

每个测试数据输出一行,为最大的和的数值。

Sample Input

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

Sample Output

100000000030

Hint

因为数据量较大,请用getchar实现整数读入,代替scanf。


解法1:读入外挂模板+自底向上的dp:

#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
typedef unsigned long long LL;
LL a[3001][3001] = {};

//仅读正整数的读入外挂
template <typename T>
inline void read(T& x) {
    char ch; while (!((((ch=getchar())>='0') && (ch <= '9')) || (ch == '-')));
    x = ch-'0'; while (((ch=getchar())>='0') && (ch <= '9')) x = x*10+ch-'0';
}

int main() {
    int n, i, j, now, T;
    //freopen("in.txt","r",stdin);
    read(T);
    while (T--) {
    	read(n);
        for(i=1;i<=n;i++)
        {
        	for(j=1;j<=i;j++)
        	{
        		read(a[i][j]);
			}
		}
		for(i=n-1;i>=1;i--)
		{
			for(j=1;j<=i;j++)
			{
				a[i][j]=a[i][j]+max(a[i+1][j],a[i+1][j+1]);
			}
		}
		printf("%I64d\n",a[1][1]);
    }
    return 0;
}

解法二更加优化:来自学长的博客http://blog.youkuaiyun.com/code4101/article/details/40109333

#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
typedef unsigned long long LL;

//仅读正整数的读入外挂
template <typename T>
inline void read(T& x) {
    char ch; while (!((((ch=getchar())>='0') && (ch <= '9')) || (ch == '-')));
    x = ch-'0'; while (((ch=getchar())>='0') && (ch <= '9')) x = x*10+ch-'0';
}

int main() {
    int n, i, j, now, T;

    read(T);
    while (T--) {
    	read(n);

        LL a[2][3001] = {};
        for (now = i = 1; i <= n; i++) {
            now ^= 1;
            for (j = 1; j <= i; j++) {
                read(a[now][j]);
                a[now][j] += max(a[now^1][j-1], a[now^1][j]);
            }
        }
        cout << *max_element(&a[now][1], &a[now][n+1]) << "\n";
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值