经典最大连续子序列,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[];
int main()
{
int k;
scanf("%d", &k);
int i;
for (i = ; i < k; i++)
{
scanf("%d", &a[i]);
}
vector<int>dp(k + , -);
vector<int>s(k + , );
dp[] = a[];
for (i = ; i < k; i++)
{
dp[i] = max(dp[i - ] + a[i], a[i]);
if (dp[i] == dp[i - ] + a[i])
s[i] = s[i - ];
else
s[i] = i;
}
int start, end;
int max = dp[];
int j = ;
for (i = ; i < k; i++)
{
if (dp[i] > max)
{
max = dp[i];
j = i;
}
}
bool flag = false;
for (i = ; i < k; i++)
{
if (a[i] > )
flag = true;
}
if (max >= )
{
/*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[], a[k - ]);
}
}