1007 Maximum Subsequence Sum(25 分)

1007 Maximum Subsequence Sum(25 分)

Given a sequence of K integers { N1​​, N2​​, ..., NK​​ }. A continuous subsequence is defined to be { Ni​​, Ni+1​​, ..., Nj​​ } where 1ijK. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10
-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:

10 1 4


//本题求 子序列中元素和的最大值  输出和的最大值,并输出此子序列的第一个元素和最后一个元素
//       若序列中元素全部为负值,则输出0 和序列的第一个和最后一个元素
//       若满足条件的子序列不唯一,则输出i和j最小的序列

/*联机法,时间复杂度为O(n),耗时7ms
*只扫描一遍序列,扫描的同时做累加。
*判断累加当前元素后的thisSum,如果比记录过的maxSum大则更新,
*如果比maxSum小且为负,那么丢弃构成thisSum的子串,从下一个元素开始另起一个子串
*/
#include<stdio.h>
#include<iostream>

using namespace std;

int main()
{
    int K;
    cin >> K;
    int N[10000];
    bool negative = true;
    for(int i = 0;i < K;i++)
    {
        cin >> N[i];
        if(N[i] >= 0)
        {
            negative = false;
        }
    }

    if(negative)//全为负数
    {
        cout << "0 " << N[0] << " " << N[K-1] << endl;
        return 0;
    }

    int maxsum = N[0],maxstart = 0,maxend = 0;//最大和,子序列的第一个元素和最后一个元素在原序列中的位置
    int sum = 0,start = 0,end = 0;//当前遍历的和,及子序列开始和结束的位置
    for(int i = 0;i < K;i++)
    {
        sum += N[i];

        if(maxsum < sum)
        {
            maxsum = sum;
            maxstart = start;
            end = i;
            maxend = end;
        }
        else if(sum < 0)
        {
            sum = 0;
            start = i+1;
            end = i+1;
        }

    }

    cout << maxsum << " " << N[maxstart] << " " << N[maxend] <<endl;

    return 0;
}

方法2:枚举法

/*方法一:穷举法:时间复杂度为O(n^2),耗时57ms*/
#include<stdio.h>
#include<iostream>

using namespace std;

int main()
{
    //step1:输入参数
    int K;
    cin >> K;
    int N[10000];
    for(int i = 0;i < K;i++)
    {
        cin >> N[i];
    }

    //step2::K个数均为负数时,输出0和第一个及最后一个元素
    int p = 0;
    for(int i = 0;i < K;i++)
    {
        if(N[i] < 0)
        {
            p++;
        }
    }
    if(p == K)
    {
        cout << "0 " << N[0] << " " << N[K-1] << endl;
        return 0;
    }

    //step3:K个数不全为负数的情况

    //统计以i为起点的子序列的最大和
    int maxsum[10000];//统计以i为起点的子序列和的最大值
    int end[10000];//统计以i为起点的子序列有最大和时的最后一个元素在原序列中的位置
    
    for(int i = 0;i < K;i++)//以i为起点
    {
        maxsum[i] = N[i];
        end[i] = i;
        int sum = N[i];//统计和
        for(int j = i+1;j < K;j++)//以j为终点
        {
            sum += N[j];
            if(maxsum[i] < sum)
            {
                maxsum[i] = sum;
                end[i] = j;
            }
        }
    }

    //比较以i为起点的最大和的大小
    int max = maxsum[0];//最大和
    int s = 0,e = end[0];//最大和对应的第一个元素和最后一个元素在原序列中对应的位置

    for(int i = 0;i < K;i++)
    {
        if(max < maxsum[i])
        {
            max = maxsum[i];
            s = i;
            e = end[i];
        }
    }

    //step4:输出结果
    cout << max << " " << N[s] << " " << N[e] <<endl;

    return 0;
}
原文地址:https://www.cnblogs.com/meiqin970126/p/9600087.html