题目描述
给出一个长度为n的序列a,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个整数,表示序列的长度n。
第二行有n个整数,第i个整数表示序列的第i个数字a_i。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #1
7
2 -4 3 -1 2 -4 3
输出 #1
4
说明/提示
样例 #1 解释
选取[3,5]子段{3,−1,2},其和为4。
数据规模与约定
- 对于40%的数据,保证1≤n≤2×10^3。
- 对于100%的数据,保证1≤n≤2×10^5,-10^4≤a_i≤10^4。
分析:
这道题最好用动态规划,用一个数组dp[i]存储当前的最大子段和,也就是当n=i时的最大子段和,接下来我们要找出状态转移方程。
而状态转移方程是什么呢?我们可以想一想,当a[i]为负数,如果n=i-1时的最大子段和比这个负数a[i]还小,那n=i时的最大子段和就是a[i]。当a[i]为正数,如果n=i-1时的最大子段和为负数的时候,加上了a[i]并不比a[i]本身大。所以状态转移方程也就是dp[i]=max(dp[i]-1+a[i],a[i])。但因为有时候dp[n]也不是最优答案,于是要用一个变量保存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.序列有负数。但只要考虑完所有情况,找到状态转移方程就好了。
---------------------------------------------------------------------------------------------------------------------------------
点赞+关注,刷题不迷路!!!!!!!!!!!!!!!!!!
---------------------------------------------------------------------------------------------------------------------------------