时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述 给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首尾是相连的。数组中一个或多个连续元素可以组成一个子数组,其中存在这样的子数组arr[i],…arr[n-1],arr[0],…,arr[j],现在请你这个ACM_Lover用一个最高效的方法帮忙找出所有连续子数组和的最大值(如果数组中的元素全部为负数,则最大和为0,即一个也没有选)。 输入 输入包含多个测试用例,每个测试用例共有两行,第一行是一个整数n(1=<n<=100000),表示数组的长度,第二行依次输入n个整数(整数绝对值不大于1000)。 输出 对于每个测试用例,请输出子数组和的最大值。 样例输入 6 1 -2 3 5 -1 2 5 6 -1 5 4 -7 样例输出 10 14 思路:最开始自己想了一种方法,将数组延伸到2n-1,即a[i+n]=a[i].然后按照求最大子串和来求解,但是交上去错了,后来找到数据发现,如果出现中间的一段序列为负值,但是不会使累加值为负,则计算出的结果是原串的最大子串和,跟自己构造的那个串没关联。然后参考别人的思路,即:1.如果最大的子串和在原串中,则求出原串的最大子串和的值就是结果 2.如果最大的子串和序列包含跨越了尾部跟头部的序列,则用总的串和减去原串中的最小的子串和即为结果。#include <stdio.h>#include <string.h>#include <algorithm>int s[100005];int main(){ using namespace std; int n; int i,j; int sum,min_s,max_s,a,b; while(~scanf("%d\n",&n)) { min_s = 0x3f3f3f3f; max_s = -0x3f3f3f3f; a = b = 0; sum = 0; for(i=0; i<n; i++) { scanf("%d",&s[i]); } for(i=0; i<n; i++) { sum += s[i]; a += s[i]; b += s[i]; min_s = min(a , min_s); max_s = max(b , max_s); if( a > 0) { a = 0; } if( b < 0) { b = 0; } } printf("%d\n",max(sum-min_s , max_s)); } return 0;}
ps: 还有一种思路,就是先找出整个字串的最小序列和,然后再从他的下一位开始找最大序列和,之后就跟NYOJ-44字串和的求法一样啦。但是这个有点麻烦,还要处理数组的坐标问题。