【ACM】最大连续子段和

最大连续子段和

定义
给定n个整数(可能为负数)组成的序列a[1…n],求该序列中形如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的数字均为0的时候,最大子段和定义为0。
方法一:
在不考虑时间的情况下,使用循环暴力的方法,求出序列的所有子段和。该方法会有3层循环嵌套。时间复杂度为O(n^3)。

#include <cstdio>
#include <algorithm>
#define maxn 1000
using namespace std;
int sum[maxn][maxn]={0}; //sum[i][j]表示从i到j的元素之和
int main()
{
    int a[maxn];
    int n;  //元素的个数
    scanf("%d",&n);
    for(int i=0;i<n;i++)
       scanf("%d",&a[i]);
    for(int i=0;i<n;i++)
       for(int j=i;j<n;j++)
         for(int k=i;k<=j;k++)
            sum[i][j] += a[k];
    int _max = -50000for(int x=0;x<n;x++)
       for(int y=x;y<n;y++)
         if(sum[x][y] > _max)
           _max = sum[x][y];
     printf("%d\n",_max); 
     return 0; 
 }

在初始化 _max的时候,应该使 _max的值小于最小数据。如果只是说明为int类型,可以初始化为INT _MIN。
方法二:
在方法一的基础上sum[i][j] = Tsum[j] - Tsum[i-1]。
方法三:
利用动态规划。时间复杂度为O(n)。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
    int n,T,number;
    scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        int max = INT_MIN;
        long long sum = 0;
        int begin = 0,end = 0 ,add = 1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&number);
            sum += number;
            if(sum > max)
            {
                max = sum;
                begin = add;
                end = i;
            }
            if(sum <0)
            {
                sum = 0;
                add = i+1;
            }
        }
        printf("Case %d:\n",t);
        printf("%d %d %d\n",max,begin,end);
        if(t<T)
            printf("\n");
    }
    return 0;
}

如果前n-1项和为整数,因为是连续项的和,所以只有2种选择,加上第n项(即使第n项为负数),或者舍弃前n-1项,第n项起构成新的连续子段。若前n-1项的和是负的,那么应该舍弃,使n项构成新的子段。若前n-1项是正的,那么即使第n项是负的也应该进行选择1。_max要始终更新为最大的数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值