题目描述
给出一个长度为 n n n 的序列 a a a ,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个整数,表示序列的长度 n n n 。
第二行有 n n n 个整数,第 i i i 个整数表示序列的第 i i i 个数字 a i a_i ai 。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #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,其和为
4
4
4 。
数据规模与约定
对于
40
40%
40的数据,保证
1
1
1
≤
\le
≤
n
n
n
≤
\le
≤
2
×
1
0
3
2×10^3
2×103。
对于
100
100%
100 的数据,保证
1
1
1
≤
\le
≤
n
n
n
≤
\le
≤
2
×
1
0
5
2×10^5
2×105 ,
−
1
0
4
-10^4
−104
≤
\le
≤
a
i
a_i
ai
≤
\le
≤
1
0
4
10^4
104。
分析:
这道题最好用动态规划,用一个数组 d p i dp_i dpi 存储当前的最大子段和,也就是当 n = i n=i n=i 时的最大子段和,接下来我们要找出状态转移方程。
而状态转移方程是什么呢?我们可以想一想,当 a i a_i ai 为负数,如果 n = i − 1 n=i-1 n=i−1 时的最大子段和比这个负数 a i a_i ai 还小,那 n = i n=i n=i 时的最大子段和就是 a i a_i ai 。当 a i a_i ai 为正数,如果 n = i − 1 n=i-1 n=i−1 时的最大子段和为负数的时候,加上了 a i a_i ai 并不比 a i a_i ai 本身大。设 t = i − 1 t=i-1 t=i−1 ,所以状态转移方程也就是 d p i = m a x ( d p t + a i , a i ) dp_i=max(dp_t+a_i,a_i) dpi=max(dpt+ai,ai) 。但因为有时候 d p n dp_n dpn 也不是最优答案,于是要用一个变量保存 d p dp dp 数组中的最大值,其他的输入输出我就不说了,下面展示代码。
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[200005],dp[200005];
int main(){
cin>>n;
for(int i = 1;i <= n;i++) cin>>a[i];
dp[1] = a[1];//因为题目说非空,所以开始要给dp[1]赋值
int mx = -214748364;//保存dp数组中的最大值
for(int i = 2;i <= n;i++)
{
dp[i] = max(dp[i-1] + a[i],a[i]);//dp方程式
mx = max(dp[i],mx);//找最优答案
}
cout<<mx;
return 0;
}
总结:
题目中有许多坑:1.子段要连续。2.子段要非空。3.序列有负数。但只要考虑完所有情况,找到状态转移方程就好了。
---------------------------------------------------------------------------------------------------------------------------------
点赞+关注,刷题不迷路!!!!!!!!!!!!!!!!!!
---------------------------------------------------------------------------------------------------------------------------------