炸弹
问题描述
高老大又在鼓捣炸弹了,这不,启动了一个了。
英明英勇的老大又在跟他的部下们表演空手光速拆炸弹了。
炸弹上是一个圆盘,圆盘上顺时针写着
N
个数。
其实这个炸弹就是要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,使得这些数字的和最大,然后输入这个最大的和,计时就会停止。
现在你被老大要求上台表演,时间是
输入
输入文件名为Bomb.in。
输入第一行包含一个正整数
N
,表示数字的个数。
第二行包含
输出
输出文件名为Bomb.out。
输出包含一个整数,为最大的可以得到的和。
输入样例
8
2 -4 6 -1 -4 8 -1 3
输出样例
14
数据范围
对于
30%
的数据
1<=N<=200
;
对于
70%
的数据
1<=N<=10000
;
对于
100%
的数据
1<=N<=100000
, 答案在longint范围内。
Solution
首先,我们假设这不是一个环。
从
n
处把它断开。
然后就是
环的情况怎么处理呢?
我们将一个方案分成两部分,一部分从
1
开始递增,一部分从
然后用动归就可以求出末端不超过
i
且从
Code
#include <iostream>
#include <cstdio>
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int n,ans;
int w[100010];
int f[100010];
int f1[100010];
int f2[100010];
int s1[100010];
int s2[100010];
int main(){
freopen("bomb.in","r",stdin);
freopen("bomb.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n;i++){
f[i]=Max(f[i-1]+w[i],w[i]);
s2[i]=s2[i-1]+w[i];
f2[i]=Max(f2[i-1],s2[i]);
ans=Max(ans,f[i]);
}
for(int i=n;i>=1;i--){
s1[i]=s1[i+1]+w[i];
f1[i]=Max(f1[i+1],s1[i]);
ans=Max(ans,f2[i-1]+f1[i]);
}
printf("%d\n",ans);
return 0;
}