字串和

子串和
时间限制: 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;
}                        

猜你喜欢

转载自blog.csdn.net/LX333XL/article/details/80081594