子串和(nyoj_44)

子串和

时间限制: 5000 ms  |  内存限制: 65535 KB
难度: 3
描述
给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。
输入
第一行是一个整数N(N<=10)表示测试数据的组数)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的一行里有n个整数I(-100=<I<=100),表示数列中的所有元素。(0<n<=1000000)
输出
对于每组测试数据输出和最大的连续子串的和。
样例输入
1
5
1 2 -1 3 -2
样例输出
5
提示

输入数据很多,推荐使用scanf进行输入


用dp方法做

b数组保存的是最大连续子列和的总和。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;

int a[1123456];
int b[1123456];

int main()
{
    int c;
    scanf("%d", &c);
    while(c--){
        int n;
        int i;
        scanf("%d", &n);
        for(i = 0;i < n;i++){
            scanf("%d", &a[i]);
        }
        for(i = 0;i < n;i++){
            b[i] = max(b[i-1]+a[i],a[i]);//b[i]的状态由前一个状态是否为0来决定,如果小于0,那末加上a[i],连续子列和必定减少,所以只有当b[i-1]>0时,b[i]的值才加上a[i],
        }
        int max = b[0];
        for(i = 1;i < n;i++){
            if(b[i] > max){
                max=  b[i];
            }
        }
        printf("%d\n", max);
    }

    return 0;
}

还有一种算法叫做在线处理算法,这是看网易云课堂数据结构课的时候老师讲的,总之只听名字就好大上;具体证明代码如下,先看懂dp的方法啊,

感觉在线处理就是对dp的一种空间优化(只针对这个题目)

如果懂了dp的话,下面代码很容易理解,但是真确性不好证明啊,满满的全都是智商啊~~~

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define inf -0x3f3f3f3f

int main()
{
    int c;
    scanf("%d", &c);
    int a, max, sum, n;
    while(c--){
        scanf("%d", &n);
        max = inf;
        sum = 0;
        for(int i = 0;i < n;i++){
            scanf("%d", &a); 
            sum += a;<span style="white-space:pre">	</span> <span style="font-family: Arial, Helvetica, sans-serif;">// 只有来一个数,必定加到sum里面,能够做到及时处理,这就是在线处理,o(n)的时间复杂度,</span>
            if(sum > max){
                max = sum;// //如果最大连续字段和比max还要大,则更新max
            }
            if(sum < 0){
                sum = 0;//如果sum小于0,那么sum加上后面的数字必定使后面的字段和变小,这时候我们就重新开始计算最大连续字段和,即隔开与前面的所有数字,重新计算新的最大连续字段和(那之前的最大连续字段和去哪了??? 被我们保存到了sum里面了),感觉这就是代码的核心部分,想通了这一点就理解这题了。
            }
        }
        printf("%d\n", max);
    }

    return 0;
}


你可能感兴趣的:(子串和(nyoj_44))