子串和
时间限制:
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进行输入
最大子串和,用这样动态更新的方法来做,比较省时间,谈谈个人对这个方法的理解:
无论给出的序列是什么样的,他的最大子串和肯定是存在的,所以现在的出发点就基于此,一个变量 tp 统计每次增加一个元素的值能达到的数值,另一个 sum 来记录最大值,每加入一个元素,tp 改变,比较 tp 是否超过了现在的最大值 sum 如果超过了,那么就更新 sum 为 tp的值,因为现在最大的值是 tp 的值了,然后来讨论 tp 的更新处理,比较容易想到,如果本来前 n 项的和(从某一个起点开始的tp 的值)还是正的,结果多加了后一项之后,突然这个 tp 变成负的了,那么证明这一项是个非常大的负数,那么最大的子串和的序列肯定不包含这一个元素,然后继续求子串和,就直接从后一项开始了.把刚才那一项跳过,就这样更新下去,最终求得的肯定是最大子串的和,因为我们只在当前子串和 tp 比 sum 大的时候进行更新,否则不更新,而 tp 这个变量,可以把所有可能达到最大和的子串的和都求了一遍,所以最大的和一定能记录下来,只是,这个子串并没有记录下来,只记录了这个最大的值而已,如果想记录这个序列,估计还要再想解决办法.....自己没理解透彻,暂时不赘述了.....
注意这个题的坑,初始化的时候不能初始化为 0 ,要初始化为一个最小值........
#include<stdio.h> #define maxn 1000005 int x[maxn],n; void solve() { int tp,sum; tp=0;sum=-maxn; for(int i=0;i<n;++i) { tp+=x[i];//累加 if(tp>sum)//比记录的值大 { sum=tp;//更新 } else if(tp<0)//小于零,就重新开始 { tp=0; } } printf("%d\n",sum); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%d",x+i); } solve(); } return 0; }