【51nod】最大子段和

11人阅读 评论(0) 收藏 举报
分类:

题面

以一个长为n的数列,求连续子段的最大值。

思路1

直接枚举O(n^3)TLE稳稳的

#include<iostream>
using namespace std;
int n, a[50050], ans;
int main(){
    cin>>n;
    for(int i = 1; i <= n; i++)cin>>a[i];
    for(int i = 1; i <= n; i++){//枚举起点
        for(int j = i; j <= n; j++){//枚举终点
            int t = 0;
            for(int k = i; k <= j; k++){//区间统计
                t += a[k];
            }
            ans = max(ans, t);//更新最值
        }
    }
    cout<<ans<<"\n";
    return 0;
}

前缀和优化的枚举法,O(N^2),还是TLE

#include<iostream>
using namespace std;
int n, a[50050], ans;
int main(){
    cin>>n;
    for(int i = 1; i <= n; i++){ cin>>a[i]; a[i]+=a[i-1];}
    for(int i = 1; i <= n; i++)//枚举起点
        for(int j = i; j <= n; j++)//枚举终点
            ans = max(ans, a[j]-a[i-1]);//更新最值
    cout<<ans<<"\n";
    return 0;
}

思路2

分治。以中间元素为基准,向左求出以中间元素为尾的最大子段和,向右求出以中间元素为首的最大子段和,两部分相加即横跨左右两部分的最大子段的和,三者最大即为答案。复杂度O(nlogn),可以水过,记得不开longlong会WA。

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int n, a[50050];
LL dfs(int l, int r){
    if(l==r)return a[l]>0?a[l]:0;//所给整数均为负数时和为0。
    else{
        int m = l+r>>1;
        LL ls = dfs(l,m), rs = dfs(m+1,r);//左右两段单独
        //跨中间
        LL lsum = 0, lmax = 0;
        for(int i = m; i >= l; i--){
            lsum += a[i];
            lmax = max(lmax, lsum);
        }
        LL rsum = 0, rmax = 0;
        for(int i = m+1; i <= r; i++){
            rsum += a[i];
            rmax = max(rmax, rsum);
        }
        return max(lmax+rmax,max(ls,rs));
    }
}
int main(){
    cin>>n;
    for(int i = 1; i <= n; i++)cin>>a[i];
    cout<<dfs(1,n)<<"\n";
    return 0;
}

思路3

DP(覆盖了所有状态),如果当前记录的子段的和为负数时,就要以下一个点为起点重新找子段了。复杂度O(n),AC稳稳的。

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int n, a[50050];
int main(){
    cin>>n;
    for(int i = 1; i <= n; i++)cin>>a[i];
    LL ans=0, t=0;
    for(int i = 1; i <= n; i++){
        if(t > 0)t += a[i];
        else t = a[i];
        ans = max(ans, t);
    }
    cout<<ans<<"\n";
    return 0;
}
查看评论

电子商务实战课程

-
  • 1970年01月01日 08:00

51Nod 1050 循环数组最大子段和(dp)

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 其实就是求循环数组的最大字段和 题意:给定一个长度为5000...
  • qq_33850438
  • qq_33850438
  • 2016-02-07 02:47:14
  • 994

51nod 最大子段和(Java)

1049 最大子段和 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题   N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a...
  • qq_35131940
  • qq_35131940
  • 2017-03-10 17:47:52
  • 209

51Nod-1050-循环数组最大子段和

ACM模版描述题解这里分为两种情况: 其一:从[1, n]的正常顺序的最大子段和; 其二:从开头取一部分,结尾取一部分,中间舍去,那么中间的一定是最小子段和,然后所有数据的和减去最小子段和即可。 ...
  • f_zyj
  • f_zyj
  • 2016-08-01 17:20:11
  • 302

51Nod 1049 最大子段和

N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值。当所给的整数均为负数时和为0。 例如:-2,11,-4,13...
  • qingshui23
  • qingshui23
  • 2016-05-06 20:36:22
  • 1252

51nod 最大子段和

给出一个整数数组a(正负数都有),如何找出一个连续子数组(可以一个都不取,那么结果为0),使得其中的和最大? 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4...
  • z1192277815
  • z1192277815
  • 2016-08-17 19:07:33
  • 549

51Nod 1049 最大子段和(简单DP)

1049 最大子段和 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 N个整数组成的序列a[1],a[...
  • zwj1452267376
  • zwj1452267376
  • 2016-02-10 15:55:01
  • 787

【51nod 教程】最大子段和问题(动态规划)

给出一个整数数组a(正负数都有),如何找出一个连续子数组(可以一个都不取,那么结果为0),使得其中的和最大? 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20...
  • Manton_dong
  • Manton_dong
  • 2017-08-09 21:01:08
  • 91

51Nod 1050 循环数组最大子段和 (最大字段和)

1050 循环数组最大子段和 N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈...
  • bmicnj
  • bmicnj
  • 2017-03-04 13:22:19
  • 439

51nod 1050 循环数组最大子段和

题目: N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑...
  • qq_24477135
  • qq_24477135
  • 2016-01-24 11:39:31
  • 758
    个人资料
    持之以恒
    等级:
    访问量: 3万+
    积分: 1353
    排名: 3万+
    文章存档