A1007 Maximum Subsequence Sum (25 分)

Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to be { N​i​​, N​i+1​​, ..., N​j​​ } where 1≤i≤j≤K. 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

题意:

给一个数字序列a1, a2, a3,...,an,求i,j (1<= i <= j <= n),使得ai+...+aj 最大,输出最大和以及ai, aj. 如果有多种方案,那么输出其中i, j最小的一组。如果所有数都小于0,那么认为最大和为0,并输出首尾元素

思路:

典型的DP问题

dp[i] 存放以a[i]为结尾的连续序列最大和, s[i] 存放dp[i] 取得最大序列和时的a从哪一个元素开始。

  1. 最大和时本身:dp[i] = a[i], s[i] = i
  2. 最大和有多个元素为:dp[i - 1] + a[i], s[i] = s[i - 1]

难点在于 s[i] 的建立

所有数小于0的情况应该先处理,并无难度,只是增加判断

注意:

  1. 题目要求输出i, j 最小的方案,因此在计算时,第二种情况的优先级更高,而且最后dp[i] > MAX 时才更新k,而不是dp[i] >= MAX 
#include <cstdio>
const int maxn = 10010;
int a[maxn], dp[maxn];
int s[maxn] = {0};
int main(){
    int n;
    scanf("%d", &n);
    bool flag = false;      //表示数组中是否全小于0
    for(int i = 0; i < n; i++){
        scanf("%d", &a[i]);
        if(a[i] >= 0)
            flag = true;
    }
    if(flag == false){
        printf("0 %d %d\n", a[0], a[n - 1]);
        return 0;
    }
    //边界
    dp[0] = a[0];
    for(int i = 1; i < n; i++){
        //状态转移方程
        if(dp[i - 1] + a[i] > a[i]){
            dp[i] = dp[i - 1] + a[i];
            s[i] = s[i - 1];
        }
        else{
            dp[i] = a[i];
            s[i] = i;
        }
    }
    int k = 0;
    for(int i = 1; i < n; i++){
        if(dp[i] > dp[k]){
            k = i;
        }
    }
    //注意s[k]存放的是下标,a[s[k]]是取出第一个元素
    printf("%d %d %d\n", dp[k], a[s[k]], a[k]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_35093872/article/details/87976899