最大子段和(C++,DP)

该博客介绍了一种动态规划的方法来解决找出给定序列中具有最大和的连续非空子段的问题。通过逐个处理序列元素,不断更新最大子段和,最终得出结果。代码示例使用C++实现,适用于数据规模较小的情况。

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

题目描述

给出一个长度为 nnn 的序列 aaa,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 nnn

第二行有 nnn 个整数,第 iii 个整数表示序列的第 iii 个数字 aia_iai

输出格式

输出一行一个整数表示答案。

样例 #1

样例输入 #1

7
2 -4 3 -1 2 -4 3

样例输出 #1

4

提示

样例 1 解释

选取 [3,5][3, 5][3,5] 子段 {3,−1,2}\{3, -1, 2\}{3,1,2},其和为 444

数据规模与约定
  • 对于 40%40\%40% 的数据,保证 n≤2×103n \leq 2 \times 10^3n2×103
  • 对于 100%100\%100% 的数据,保证 1≤n≤2×1051 \leq n \leq 2 \times 10^51n2×105−104≤ai≤104-10^4 \leq a_i \leq 10^4104ai104

解题思路:

通过样例输入进行说明

首先读入2,把2作为前缀

然后读入-4,2+(-4)=-2>-4,所以如果-4是最大子段的一部分,2一定也是最大子段的一部分

再读入3,3+(-2)=1<3,所以如果3是最大子段的一部分,2和-4一定不是最大子段的一部分

再读入-1,3+(-1)=2<3,所以如果-1是最大子段的一部分,3一定也是最大子段的一部分

再读入2,2+2=4>2,所以如果2是最大子段的一部分,3和-1一定也是最大子段的一部分

再读入-4,4+(-4)=0>-4,所以如果-4是最大子段的一部分,3、-1、2一定也是最大子段的一部分

最后读入3,0+3=3==3,所以如果3是最大子段的一部分,3、-1、2、-4一定不是最大子段的一部分

本质就是尝试给每一个数连接一个前缀,使这个数变得比自己大,如果比自己小,那么就不连接这个前缀

每次比较连接前缀后和不连接前缀二者的大小时,我们都保证了得到的是最大的前缀,同时有可能我们得到的最大前缀就是所谓的最大子段

所以本题采用的策略并不能保证最后得到的是最大子段,但我们一定曾经得到过最大子段

再加上一个变量max_num,比较每次连接的结果并存入其中

所以在读入3之后虽然我们丢弃了2和-4,但我们已经把22、-4这两个子段中最大者存入了max_num

最后只需要输出max_num即可

AC代码如下

#include <iostream>
using namespace std;

int num_arr[2] = { 0 };
int max_num = 0;

int main() {
	int n, temp;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> temp;
		if (i < 1) {
			max_num = temp;
			num_arr[0] = temp;
			continue;
		}
		num_arr[i % 2] = max(temp, temp + num_arr[(i + 1) % 2]);
		max_num = num_arr[i % 2] > max_num ? num_arr[i % 2] : max_num;
	}

	cout << max_num;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WitheredSakura_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值