最大子段和

题目描述

  给出一段序列,选出其中连续且非空的一段使得这段和最大。

输入格式

  第一行是一个正整数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%的数据,有N2000。

对于100%的数据,有N200000。

分析:

  哎,感觉自己就是憨憨,一开始想用设置分段为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 } 

 

posted @ 2020-04-21 21:55  关注我更新论文解读  阅读(88)  评论(0编辑  收藏  举报