Problem Description
给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
注意:本题目要求用分治递归法求解,除了需要输出最大子段和的值之外,还需要输出求得该结果所需的递归调用总次数。
递归调用总次数的获得,可以参考以下求菲波那切数列的代码段中全局变量count的用法:
#include
int count=0;
int main()
{
int n,m;
int fib(int n);
scanf("%d",&n);
m=fib(n);
printf("%d %d\n",m,count);
return 0;
}
int fib(int n)
{
int s;
count++;
if((n==1)||(n==0)) return 1;
else s=fib(n-1)+fib(n-2);
return s;
}
Input
第一行输入整数n(1<=n<=50000),表示整数序列中的数据元素个数;
第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。
Output
一行输出两个整数,之间以空格间隔输出:
第一个整数为所求的最大子段和;
第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。
Example Input
6 -2 11 -4 13 -5 -2
Example Output
20 11
#include<stdio.h> #include<string.h> #include<stdlib.h> #define INITLISTSIZE 50000 #define INCREMENT 10 #define OVERFLOW -2 #define ERROR -1 #define OK 1 typedef int Elemtype; typedef int Statu; int count; typedef struct node { Elemtype *elem; int length; int listsize; } Sqlist; Statu Initlist(Sqlist &L); Statu Insertlist(Sqlist &L, int i, int e); Statu Dellist(Sqlist &L, int i); int Changelist(Sqlist L); int Divide(Sqlist L, int l, int r); Statu Destroylist(Sqlist &L); int main() { int n, i, j; Sqlist L; Initlist(L); scanf("%d", &j); for(i = 0; i < j; i++) { int k; scanf("%d", &k); Insertlist(L, i + 1, k); } count = 0; n = Divide(L, 0, j - 1); printf("%d %d\n", n, count); Destroylist(L); } Statu Initlist(Sqlist &L) { L.elem = (Elemtype *)malloc(INITLISTSIZE * sizeof(Elemtype)); if(!L.elem) return OVERFLOW; L.length = 0; L.listsize = INITLISTSIZE; return OK; } Statu Insertlist(Sqlist &L, int i, int e) { Elemtype *newbase; if(i < 1 || i > L.length + 1) return ERROR; if(L.length >= L.listsize) { newbase = (Elemtype *)realloc(L.elem, (L.listsize + INCREMENT) * sizeof(Elemtype)); if(!newbase) return OVERFLOW; L.elem = newbase; L.listsize += INCREMENT; } for(int j = L.length; j >= i; j--) L.elem[j] = L.elem[j - 1]; L.elem[i - 1] = e; ++L.length; return OK; } Statu Dellist(Sqlist &L, int i) { if(i < 1 || i > L.length) return OVERFLOW; for(int j = i - 1; j < L.length; j++) L.elem[j] = L.elem[j + 1]; --L.length; return OK; } int Changelist(Sqlist L) { int ThisSum, MaxSum, j; ThisSum = MaxSum = 0; for(j = 0; j < L.length; j++) { ThisSum += L.elem[j]; if(ThisSum > MaxSum) MaxSum = ThisSum; else if(ThisSum < 0) ThisSum = 0; } return MaxSum; } Statu Destroylist(Sqlist &L) { if(L.elem) { free(L.elem); L.length = 0; L.listsize = 0; } else return ERROR; return OK; } int Divide(Sqlist L, int l, int r) { int MaxLSum, MaxRSum; int MaxLBSum, MaxRBSum; int LBSum, RBSum; int Center, i; count++; if(l == r) { if(L.elem[l] > 0) return L.elem[l]; else return 0; } Center = (l + r)/2; MaxLSum = Divide(L, l, Center); MaxRSum = Divide(L, Center + 1, r); MaxLBSum = 0; LBSum = 0; for(i = Center; i >= l; i--) { LBSum += L.elem[i]; if(LBSum > MaxLBSum) MaxLBSum = LBSum; } MaxRBSum = 0; RBSum = 0; for(i = Center + 1; i <= r; i++) { RBSum += L.elem[i]; if(RBSum > MaxRBSum) MaxRBSum = RBSum; } if(MaxLSum > MaxRSum && MaxLSum > MaxLBSum + MaxRBSum) return MaxLSum; else if(MaxRSum > MaxLSum && MaxRSum > MaxLBSum + MaxRBSum) return MaxRSum; else return MaxLBSum + MaxRBSum; }