1082: 循环数组最大子段和 [DP]
时间限制: 1 Sec 内存限制: 128 MB提交: 19 解决: 6 状态
题目描述
KACA在做了最大子段和问题之后,思考若数组可以首尾相接的话最大子段和应该是多少。
输入
有多组测试数据。
每一组的第一行是一个整数 n 。
下面一行是 n 个以空格分开的整数 ai 。
1≤N≤10000
0≤|ai|≤106
输出
对于每一组数据,输出当数组可以首位相接时的最大子段和,占一行。
样例输入
6
-1 4 -1 -5 5 1
样例输出
9
来源
一个经典的入门DP;51Nod算法课程里的模板题;
这道题跟最大连续子段和有区别在这里涉及了循环数组,那么考虑一下其实这题求的是数组中的最小连续子段和。
然后sum减去最小连续子段和就是循环数组的最大连续子段和。
思路早就有了不过不知道为啥一直不过……
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int n;
typedef long long ll;
ll a[50010];
int main(){
while(~scanf("%d",&n)){
ll sum=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum+=a[i];
}
ll su=0;
ll su1=0;
ll ma=0;
ll ma1=0;
for(int i=1;i<=n;i++){
if(su<=0){
su=a[i];
if(su>ma){
ma=su;
}
}
else{
su+=a[i];
if(su>ma){
ma=su;
}
}
if(su1<=0){
su1=-a[i];
if(su1>ma1){
ma1=su1;
}
}
else{
su1+=(-a[i]);
if(su1>ma1){
ma1=su1;
}
}
}
printf("%lld\n",max(ma,sum-(-ma1)));
}
return 0;
}