K - 循环数组最大子段和
第2 - N+1行:N个整数 (-10^9 <= Sii <= 10^9) Output输出循环数组的最大子段和。 Sample Input
6
-2
11
-4
13
-5
-2
Sample Output
20
**************************************************************************
思路,其实我就是觉得很烦。很烦。
**************************************************************************
你可以把这个一串数字,分为以下几类:
(1)第一种,从开始最后都是递增的,也就是全加起来,就是最大值。
例:5 1 2 3 4 5
(2)第二种,中间的一部分大,两头加了,就变小了。循环也是中间的。
例:6 -1 0 5 -1 5 -1
(3)第三种,两头的大,中间一部分数值,阻隔了。循环去考虑。
例:5 5 -1 -2 5 -1
(4)第四种,就前面,或者后面的小,其余的是最大值的组成部分。
例:5 1 2 -1 0 -3 或者 5 -1 0 -3 1 2
**************************************************************************
现在我们来解决他们这些情况,就可以解决了。
(1)(4)我们用一个数值,求不循环的最大值,就可以解决掉。OK。
(2)(3)如果我们把所有的数取反,之后求最大值,得到的是不是小的部分加起来的最大值,之后再把原来的数据,加起来。他们求和,不就是最大值吗?假设原来全部数据和为ans1 ,取反求最大值为ans2,那么ans = ans1 + ans2吗?或者这样来理解,我们把原来的数据求最小值,我们用所有的数据和,减去他,ans = ans1 - (-ans2),公式不就是这个吗?只不过前者我取反求的ans2而已。
**************************************************************************
(1)(2)(3)(4)合并,二者之间不就是,去取最大值吗?
**************************************************************************
这种解释,应该能懂吧?或者还有什么情况没有考虑吗?欢迎下面留言,我将一一改正。
**************************************************************************
代码如下:
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; long long int a[50005]; int n; long long int cmp() { long long int max1 = 0; long long int num = 0; for(int i=0;i<n;i++) { if(max1<0) { max1=a[i]; } else { num = max(num,max1); max1+=a[i]; } } return num; } void print_gaibian() { for(int i=0; i<n; i++) { a[i] = -a[i]; } } int main() { scanf("%d",&n); long long int ans=0,ans1=0,ans2=0; for(int i=0;i<n;i++) { scanf("%lld",&a[i]); ans+=a[i]; } ans1 = cmp(); print_gaibian(); ans2 = cmp(); ans = max(ans1,ans+ans2); printf("%lld\n",ans); return 0; }