子串和(nyoj_44)

来源:互联网 发布:更改歌曲属性数据无效 编辑:程序博客网 时间:2024/05/22 00:25

子串和

时间限制: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)
输出
对于每组测试数据输出和最大的连续子串的和。
样例输入
151 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 -0x3f3f3f3fint 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;}


0 0
原创粉丝点击