题目描述
给出一段序列,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个正整数N,表示了序列的长度。
第二行包含N个绝对值不大于10000的整数A_i,描述了这段序列。
输出格式
一个整数,为最大的子段和是多少。子段的最小长度为11。
输入输出样例
输入 #1
7
2 -4 3 -1 2 -4 3
输出 #1
4
说明/提示
【样例说明】
2,-4,3,-1,2,-4,3中,最大的子段和为4,该子段为3,-1,2
【数据规模与约定】
对于40%的数据,有N≤2000。
对于100%的数据,有N≤200000。
分析:
哎,感觉自己就是憨憨,一开始想用设置分段为1 ,2 ,3这种队列的形式来做,后来想想这样纯属枚举,肯定过不了。看了dalao的代码感觉,人家就是牛,像dalao致敬。
废话不多说,本题的主要是为了一个最大子矩阵而准备的一维题目,属于基础题。
思路:累加每个数字的和,只要不<0,继续加,虽然可能出现前缀和减小,但由于又一个maxx变量保存已出现的最大值,本不用担心找不到正确的最大值。
代码1:
1 #include<iostream>
2 using namespace std;
3 int n,j,sum,maxx;
4 int main(){
5 cin>>n>>maxx;//值得推荐的方法,赋值第一个值为最大
6 sum=maxx;//输入n
7 while(--n){
8 cin>>j;
9 sum=sum>0?sum:0;//只要前缀和不<0,还是说明后面可能出现最大值的
10 sum+=j;
11 // cout<<"sum = "<<sum<<" "<<"max ="<<maxx<<endl;
12 maxx=maxx>sum?maxx:sum;
13 }//贪心,如果负了就舍去
14 return (printf("%d",maxx))&0;//输出并return 0
15 }
代码2:采用滚动数组装一下下dalao
1 #include<cmath>
2 #include<iostream>
3 using namespace std;
4 int sum,a[2],n;//仅需要两个元素的数组
5 int main()
6 {
7 cin>>n;
8 cin>>a[1];//先读入第一个元素,这里取a[1]主要是因为后面第一次循环是i=2 开始
9 sum=a[1];
10 for(int i=2;i<=n;++i)
11 {
12 if(sum<0) sum=0;//因为第一个输入的数可能是负数,所以这个判断放for循环的最前面
13 cin>>a[i%2];//滚动
14 sum+=a[i%2];
15 a[i%2]=max(a[(i-1)%2],sum);//DP状态转移方程,判断是加了这个数使得前缀和大,还是不加大
16 }
17 cout<<a[n%2];
18 return 0;
19 }