PAT 甲级 1007 Maximum Subsequence Sum

最大连续子序列和
题目分为两步,第一步求最大和,第二步求该子序列的起始点和结束点。
首先看第一步
求子序列的最大和
定义一个sum,表示从头开始到当前位置序列之和,若sum<0,则将sum置为0,并更新答案.
这里有dp的思想,即无需管sum之前是怎么来的,只要管当前序列的值与sum的和,从而推出下一个sum。
这样一遍遍历就可以得到最大和。
接下来第二步,如何定位子序列的起始点和结束点。
结束点很好定位,在更新最大值时顺便更新即可,起始点稍微有点复杂。
首先我们考虑,起始点是从第一个开始的,然后当在i位置sum<0时,起始点就要更新为i+1,因为前缀和是负数,肯定不能取,一定要从他后面开始,sum置0也是同理。但是不能每次碰到sum<0时就更新,这样会越过最大值的位子。
那么在什么时候更新呢,我们想到了,既然与最大值的位置有关,那在更新最大值时更新起始点位置不就好了吗,我们用一个临时变量来记录可能的起始点的位置,在最大值更新时,更新起始点的值。
代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm> 
#include <cstring>
#include <cmath>
#include <vector> 
using namespace std;
int main()
{
    long long n;
    long long a[10005];
    long long sum=0;
    long long maxn,maxp,minp;
    bool flag=0;
    while(~scanf("%lld",&n))
    {
        memset(a,0,sizeof(a));
        flag=0;
        minp=1;
        int tempp=1;
        sum=0;
        long long cnt=0;
        scanf("%lld",&a[1]);
        if(a[1]>=0) flag=1;
        sum+=a[1];
        maxn=sum;
        maxp=1;
        if(sum<0)
        {
            sum=0;
            tempp=2;
            maxp=2;
            minp=2;
        }

        for(int i=2;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            if(a[i]>=0) flag=1;
            sum+=a[i];
            if(sum<0)
            {
                sum=0;
                tempp=i+1;
            }
            if(sum>maxn)
            {
                maxn = sum;
                minp= tempp;
                maxp =i;
            }
        }
        if(!flag)
        {
            printf("0 %lld %lld\n",a[1],a[n]);
            continue;
        }
        printf("%lld %lld %lld\n",maxn,a[minp],a[maxp]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值