最大子段和(SDIBTOJ 2002)

来源:互联网 发布:网络教育大专要考试吗 编辑:程序博客网 时间:2024/05/22 10:23

 算法实验3:最大子段和

            Time Limit: 1 Sec Memory Limit: 64 MB
               Submit: 3289 Solved: 1424
               [Submit][Status][Discuss]
Description

给定有n个整数(可能为负整数)组成的序列a1,a2,…,an,求该序列连续的子段和的最大值。 如果该序列的所有元素都是负整数时定义其最大子段和为0。

Input

第一行有一个正整数n(n<1000),后面跟n个整数,绝对值都小于10000。直到文件结束。

Output

输出它的最大子段和。

Sample Input

6 -2 11 -4 13 -5 -2
Sample Output

20
HINT

分别用普通O(n 3 )或O(n 2 )、分治O(nlogn)和动态规划O(n)实现。

Source

AC的代码

O(n^3)

//  O(n^3)#include <stdio.h>int main(void){    int s[1010];    int i,j,k;    int n;    int sum = 0;    int max = 0;    scanf("%d",&n);    for(i = 0; i < n; i++)        scanf("%d",s+i);    for(i = 0; i < n; i++)        for(j = i; j < n; j++){            for(k = i,sum = 0; k <= j; k++)                sum += s[k];            if(sum > max)                max = sum;        }    printf("%d\n",max);    return 0;}

O(n^2)

//  O(n^2)#include <stdio.h>int main(void){    int s[1010];    int i,j,k;    int n;    int sum = 0;    int max = 0;    scanf("%d",&n);    for(i = 0; i < n; i++)        scanf("%d",s+i);    for(i = 0; i < n; i++){        sum = 0;        for(j = i; j < n; j++){            sum += s[j];            if(sum > max)                max = sum;        }    }    printf("%d\n",max);    return 0;}

O(nlogn)

//  O(nlogn)#include <stdio.h>int maxchs(int*,int,int);int main(void){    int s[1010];    int i,j,k;    int n;    int sum = 0;    int max = 0;    scanf("%d",&n);    for(i = 0; i < n; i++)        scanf("%d",s+i);    printf("%d\n",maxchs(s,0,n-1));    return 0;}int maxchs(int *s, int left, int right){    int i;    int sum = 0;    if(left == right)        if(s[left] > 0)            sum = s[left];        else            sum = 0;    else{        int mid = (left + right)/2;        int lsum = maxchs(s, left, mid);        int rsum = maxchs(s, mid+1, right);        int sl = 0;        int sr = 0;        int suml = 0;        int sumr = 0;        for(i = mid; i >= left; i--){            sl += s[i];            if(sl > suml)                suml = sl;        }        for(i = mid+1; i <= right; i++){            sr += s[i];            if(sr > sumr)                sumr = sr;        }        sum = suml+sumr;        if(sum < lsum)            sum = lsum;        if(sum < rsum)            sum = rsum;    }    return sum;}

O(n)
从前向后遍历一遍,一旦和小于等于0,则将和置位0,再向后加

//  O(n)#include <stdio.h>int main(void){    int s[1010];    int i,j,k;    int n;    int sum = 0;    int max = 0;    scanf("%d",&n);    for(i = 0; i < n; i++)        scanf("%d",s+i);    for(i = 0; i < n; i++){        if(sum > 0)            sum += s[i];        else            sum = s[i];        if(sum > max)            max = sum;    }    printf("%d\n",max);    return 0;}
原创粉丝点击