最大和(codevs 1648)
题目描述 Description
N个数围成一圈,要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,问能形成的最大的和。
输入描述 Input Description
第一行输入N,表示数字的个数,第二行输入这N个数字。
输出描述 Output Description
输出最大和。
样例输入 Sample Input
8
2 -4 6 -1 -4 8 -1 3
样例输出 Sample Output
14
数据范围及提示 Data Size & Hint
数据说明:
40% 1<=N<=300
60% 1<=N<=2000
100% 1<= N<=100000,答案在longint范围内。
/* O(n^2)的做法:枚举断点,再算最大子段和,TLE 60分 正解:环形的最大连续子段和有两种情况,一种是在1~n的,或者是在1~2*n的,如果是在 1~2*n中,显然可知ans等于sum减去1~n中的最小连续字段和 */ #include<cstdio> #include<iostream> #include<cstring> #define M 100010 #define INF 2000000000 using namespace std; int a[M],f[M],ans=-INF; int main() { int n,sum=0;; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]), sum+=a[i]; for(int i=1;i<=n;i++) { if(f[i-1]>0)f[i]=f[i-1]+a[i]; else f[i]=a[i]; ans=max(ans,f[i]); } int p=INF; memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) { if(f[i-1]<0)f[i]=f[i-1]+a[i]; else f[i]=a[i]; p=min(p,f[i]); } ans=max(ans,sum-p); printf("%d",ans); return 0; }