最大子段和 题解

最大子段和
时间限制:1秒 内存限制:128M
题目描述

       小可喜欢思考人生的意义,她发现每个人的一生不可能一帆风顺,或多或少总要经过坎坷挫折的考验。于是她将人的一生的每个关键时间点以数值表示,快乐越高,分值越高,痛苦值越高,分值越低甚至会成为负数。进一步研究,她又发现人的记忆总是会记住那些快乐的时光,而淡忘痛苦的时光。于是小可想统计出某个人连续最大的一段时光总和是多少。

       即给定K个整数的序列{N1, N2, N2,……, NK},其任意连续子序列可表示为{Ni, Ni+1,……, Nj},其中1≤i≤j≤K。

       最大连续子序列是所有连续子序列中元素和最大的一个,例如,给定序列{-2,  11,-4, 
13,-5,-2},其最大连续子序列为{11,-4, 
13},最大和为20。

输入描述

第一行是一个正整数N<=100000,表示了序列的长度。

第二行包含N个绝对值不大于10000的整数,描述了这段序列。

输出描述

一个整数,为最大的子段和是多少。子段的最小长度为1。

样例
输入
7
2 -4 3 -1 2 -4 3
输出
4
今天为大家带来一道简单的dp题------最大子段和的题解。读完题后,此题的思路便会十分清晰。用max()函数作比较来确定以此点起始的子段是否为最大。将每次求出的子段和与最大值记录器ans比较,将最大值计入ans,ans即为正解。
话不多说,附上AC代码。

#include<iostream>
#include<cstring>
using namespace std;
int h(int f[],int n)
{
int a=f[1],ans=a,i;
for(i=2;i<=n;i++)//因为a的初值已记为f[1]的值,故循环需从下标为2开始。
{
a=max(a,0)+f[i];//利用max()函数求出当时最大子段和的长度。开始讨论,如a<0,即代表之前求出的最大的子段和继续相加的长度还不如从头计数的长度。便需要抛弃原来的计数长度,将a的值重置为由此点开始的子段和,再进行新的循环。如a>0,则为之前求出的最大的子段和继续相加的长度大于从头计数的长度,即不需要重置a的值重新开始,直接加上新f[i]的值即可。
ans=max(ans,a);//"打擂台"与之前求出的最大子段和比较,求出真正的最大值。
}//核心循环,划重点
return ans;
}
int main()
{
int a[100001],f[100001],i,n;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}//输入
cout<<h(a,n);//输出函数返回值
return 0;//完美结束
}

原文地址:https://www.cnblogs.com/tcwbob/p/13402761.html