爆刷PAT(甲级)——之【1007】 Maximum Subsequence Sum (25)——最大子序列和,思维

题意: 给出一个整数序列,长度为N。然后输出这个序列的 “最大子序列和” 和以及子序列的首项、末项。

难点:

1、题目分析

N最大10000,肯定要用O(N)的算法。其实想一下,这就是一个思维题,从左边扫区间到右边,不断保存当前的累加值,用这个累加值去维护当前的最大子序列和,以及记录最大的子序列的区间范围即可

如果当前的值(和)大于已有的最大序列和,就覆盖保存;

如果当前的值(和)已经小于0了,说明当前节点是负数,而且前面一段节点都是负数。那最大序列和是不可能从这出发的。所以直接令当前的值(和)为0,从0开始重新累加即可。

扫完一遍,维护好的最大值输出即可。

2、思维要点

思维要点就一个,要理解这种扫法是可以出解的:

假设一个序列是   -1 -1 3 -1 -1 3 -1 -1

那么我们可以发现最大区间是第一个3到第二个3,这一段的区间和是 4。

这说明了什么——说明了,找区间的时候,并不能仅仅考虑  累加每一段正数区间。因为有可能正数区间之间是可以选择到同一个区间后,累加的值更大,才是答案!

那如何判断两个正数区间,夹杂着一些负数的时候,什么时候把它们合并成一个区间呢?

再看这个例子:

假设一个序列是   -1 -1 3 -1 -1  -1 3 -1 -1

或者是  -1 -1 3 -1  -1   -1  -1 3 -1 -1

我们就会发现,这两个序列,第一个序列要不要合并最大值都是3;第二个序列合并了两个3的区间之后,最大值成了2反而少了还不如不合并。

也就是说,得出结论——从左边向右边,对这个数组求和,如果当前的和sum<0,那么就肯定!肯定!不需要再把前面这段的区间和还拿到后面累加上去,然后讨论最大值了!而是,可以直接舍弃掉!也就是令sum为0!

这就是我前面概括的本题的思维点。即可A题。

3、坑点

要注意审题——题目说,如果整个区间里全是负数,那么输出的和为 0!!!!  以及把区间第一个数和最后一个数输出!

还有一个小细节,如果是  -1 0 1的话,那还是要输出 0 的,标准输出结果是  “0 0 0”;如果是 0 0 0序列的话,输出结果也应该是“0 0 0”,也就说算法还没开始的时候,最小值应该初始化为负数,而不是0.。。。

还是一道水题,大一已经做过了。今天话痨一下。

Code:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define inf 10009
#define INF 0x3f3f3f3f
#define loop(x,y,z) for(x=y;x<z;x++)

int n;
int num[inf];
int max_sum,sum;//最大和,以及当前和
int l,r;//临时表示的区间
int max_l,max_r;//最大和 的区间
int tag=0;//全0标志,1表示全0

void Input()
{
    cin>>n;
    int i;
    loop(i,0,n)
    {
        cin>>num[i];
        if(num[i]>=0)tag=1;
    }
}

void Solve()
{
    if(!tag)return;
    int i;
    max_sum=-INF;
    sum=0;//Init

    loop(i,0,n)
    {
        sum+=num[i];
        if(sum>max_sum)
        {
            max_sum=sum;
            max_l=l;
            r=i;
        }
        if(sum<=0)
        {
            sum=0;
            l=i+1;
        }
    }
}

void Output()
{
    if(!tag)//全0
        cout<<"0 "<<num[0]<<' '<<num[n-1]<<endl;
    else
    {
        max_r=r;
        cout<<max_sum<<' '<<num[max_l]<<' '<<num[max_r]<<endl;
    }
}

int main()
{
    Input();
    Solve();
    Output();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Hide_in_Code/article/details/81539628