题目描述
给出一个长度为 nn 的序列 aa,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个整数,表示序列的长度 nn。
第二行有 nn 个整数,第 ii 个整数表示序列的第 ii 个数字 a_iai。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #1
7
2 -4 3 -1 2 -4 3
输出 #1
4
说明/提示
样例 1 解释
选取 [3, 5][3,5] 子段 {3, -1, 2}{3,−1,2},其和为 44。
数据规模与约定
思路
经典的DP动态规划题目(好像也能暴力求解),定义一个数组dp,dp数组的含义为记录以第i个数结尾的前面子串中最大的字段和。可得状态转移方程为:
dp[i]=max(dp[i-1]+num[i],num[i]);
dp[i-1]为以第i-1个数结尾的最大子段和,而dp[i-1]+num[i]的含义为前面的子段和加上当前位置的值,将之与num[i]取最大值是因为如果前面的字段和加上当前的值并不比当前的值大,那我就不需要加了呗,就取当前的值。但需要注意的是,动态规划的模板写完后dp[n]并不一定存的是最大子段和,因为若dp[i]的值为负数,则dp[i+1]的值就是num[i],而num[i]的值不一定比前面的最大字段和数大。所以每次得出dp[i]还要跟前面求出的最大值比较。
AC代码
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> num,dp;
num.resize(n+1);
dp.resize(200005);
for(int i=1;i<=n;i++)
cin>>num[i];
dp[1]=num[1];
int sum=dp[1];
for(int i=2;i<=n;i++)
{
dp[i]=max(dp[i-1]+num[i],num[i]);//状态转移方程
sum=max(dp[i],sum);//和前面最大的比较
}
cout<<sum<<endl;
return 0;
}
//2022.4.13 DP动态规划