经典最大连续子序列,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 ", max, a[s[j]], a[j]); } else if (flag == false) { printf("0 %d %d ", a[0], a[k - 1]); } }