[pat]1007 Maximum Subsequence Sum

经典最大连续子序列,dp[0]=a[0],状态转移dp[i]=max(dp[i-1]+a[i],a[i])找到最大的dp[i].

难点在于记录起点,这里同样利用动态规划s[i],如果dp[i]选择的是dp[i-1]+a[i]那么s[i]=s[i-1]dp[i]与dp[i-1]存在共同的起点,如果的dp[i]选择的是a[i],那就说明他是以a[i]为起点的新序列。s[i]=a[i].一开始想从终点一直向前遍历找到a[i]<0的下一个就是起点,有一个点无法通过24分,后来才发现这是一种极为智障的想法。比如1000 2000 -1 100 200这个序列,结果为3299 100 200,显然起点应该是1000才对。

#include <bits/stdc++.h>
using namespace std;
int a[10005];
int main()
{
    int k;
    scanf("%d", &k);
    int i;
    for (i = 0; i < k; i++)
    {
        scanf("%d", &a[i]);
    }
    vector<int>dp(k + 1, -1);
    vector<int>s(k + 1, 0);
    dp[0] = a[0];
    for (i = 1; i < k; i++)
    {
        dp[i] = max(dp[i - 1] + a[i], a[i]);
        if (dp[i] == dp[i - 1] + a[i])
            s[i] = s[i - 1];
        else
            s[i] = i;
    }
    int start, end;
    int max = dp[0];
    int j = 0;
    for (i = 1; i < k; i++)
    {
        if (dp[i] > max)
        {
            max = dp[i];
            j = i;
        }
    }
    bool flag = false;
    for (i = 0; i < k; i++)
    {
        if (a[i] > 0)
            flag = true;
    }
    if (max >= 0)
    {
        /*end = j;
        for (; j >= 0; j--)
        {
            if (a[j] < 0)
                break;
        }
        if (j == -1)
        {
            j = 0;
        }
        else if (j >= 0 && a[j] < 0)
        {
            j = j + 1;
        }
        start = j;*/
        printf("%d %d %d\n", max, a[s[j]], a[j]);
    }
    else if (flag == false)
    {
        printf("0 %d %d\n", a[0], a[k - 1]);
    }
}

猜你喜欢

转载自www.cnblogs.com/legendcong/p/9175655.html