题目
思路
题目大意:给一个数组,找到最大的连续子序列;
状态划分:以每个元素为结尾划分状态,dp[i]代表以这个元素为结尾时最大的连续子序列和,注意状态dp[i]包含第i个元素;
状态转移:对于状态i来说,可分为两种情况:加上前一状态的结果,即如果 dp[i - 1] + num[i] >= num[i],则dp[i] = dp[i - 1] + num[i];只有自己本身, 则dp[i] = num[i];
最后遍历所有状态,找到最优;
对于题目中要求输出起点,则开一个数组start[i]保存以第i个元素结尾的最大连续子序列其开始下标,在进行分类讨论时更新start数组;
有可能元素全为负,需要在输入时就判断一下;
注意,不能令ans = -1; 因为最后比较时 -1 越界了,会导致答案错误;所以乖乖地在输入时判断是不是全为负,做特殊处理吧~~
代码
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <math.h>
#include <set>
#include <map>
using namespace std;
const int maxn = 1e4 + 10;
int dp[maxn], start[maxn], num[maxn], n;
int main()
{
scanf("%d", &n);
bool flag = false;
for(int i = 0; i < n; i ++) {
scanf("%d", &num[i]);
if(num[i] >= 0) flag = true;
}
if(flag == false){
printf("%d %d %d\n", 0, num[0], num[n - 1]);
return 0;
}
//初始化状态
dp[0] = num[0], start[0] = 0;
//填充状态
for(int i = 1; i < n; i ++){
if(num[i] <= dp[i - 1] + num[i]){
dp[i] = num[i] + dp[i - 1], start[i] = start[i - 1];
}
else {
dp[i] = num[i], start[i] = i;
}
}
//遍历所有情况,找出最大,ans记录结尾元素的下标
int ans = 0;
for(int i = 0; i < n; i ++){
if(dp[i] > dp[ans]) ans = i;
}
printf("%d %d %d\n", dp[ans], num[start[ans]], num[ans]);
system("pause");
return 0;
}