题目链接
题目大意
给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。
输入与输出样例
输入
第一行是一个整数,表示序列的长度 n。
第二行有 n 个整数,第 i 个整数表示序列的第 i 个数字 a i a_i ai
7
2 -4 3 -1 2 -4 3
输出
输出一行一个整数表示答案。
4
思路
首先给出转移方程:dp[i] = max(f[i], dp[i - 1] + f[i]);
推导:对于每个数,要么选择,要么不选择,且保持连续非空。对于
f
[
i
]
f[i]
f[i] 的选取,如果选择该数能改使得此连续一段和最大,那么有
d
p
[
i
−
1
]
+
f
[
i
]
dp[i-1]+f[i]
dp[i−1]+f[i] ,把第
i
−
1
i-1
i−1之前的最大连续子段和与当前的
f
[
i
]
f[i]
f[i] 加起来;如果不选择,不满足非连续,以当前的数
f
[
i
]
f[i]
f[i] 作为连续子段的开始数,dp[i]=f[i]
。综上,推导出dp[i] = max(f[i], dp[i - 1] + f[i])
。
AC代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
long long f[200020],dp[200020];
const int inf = 0xefffffff;
int main(int argc, char* argv[])
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &f[i]);
dp[i] = 0;
}
//定义最小值,不能用0,否则WA
long long ret = inf;
for (int i = 1; i <= n; ++i)
{
dp[i] = max(f[i], dp[i - 1] + f[i]);
ret = max(ret, dp[i]);
}
printf("%lld\n", ret);
return 0;
}