max sum(最大连续区间和问题)

一、题目描述:

给定一个序列a[1],a[2],a[3]…a[n],你的工作是计算子序列的最大和。例如,给定(6,-1,5,4,-7),这个序列中的最大和是6 +(-1)+ 5 + 4 = 14。

输入

输入的第一行包含一个整数T(1<=T<=20),这意味着测试用例的数量。然后T行,每一行以一个数字N(1<=N<=100000)开始,然后N个整数(所有整数都在-1000到1000之间)。

输出

对于每个测试用例,您应该输出两行。第一行是“Case #:”,#表示测试用例的编号。第二行包含三个整数,序列中的最大和、子序列的起始位置、子序列的结束位置。如果有多个结果,则输出第一个结果。在两个案例之间输出一个空行。

二、输入输出样例:

Sample Input:
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5

Sample Output:
Case 1:
14 1 4

Case 2:
7 1 6

三、实现代码:

#include <iostream>
using namespace std;
int main()
{
	int a[100005]={0};
	int n,j,i,k; 
	int p,q,x,y;
	int fact,sum;
	int num=1;
	cin>>k;
	int count=k;
	for(j=0;j<k;j++)
	{
		cin>>n;
		for(i=0;i<n;i++)
		{
			cin>>a[i];
		}
		sum=a[0];
		fact=a[0];
		x=0,y=0,p=0,q=0;
		for(i=1;i<n;i++)
		{
			if(sum+a[i]<a[i])
			{
				sum=a[i];
				x=i;
				y=i;
			}
			else
			{
				sum=a[i]+sum;
				y++;
			}
			if(sum>fact)
			{
				fact=sum;
				p=x;
				q=y;
			}
		}
		printf("Case %d:\n",num);
		printf("%d %d %d\n",fact,p+1,q+1);
		if(j!=k-1)
		{
			printf("\n");
		}
		num++;
	}
}

四、做题思路:

这道题和之前做过的那道利润题思路基本一致,要找到连续区间的和的最大值,并且找到该区间的起点和终点。所以:我们从第一个位置开始,让起点和终点都为这个位置,然后判断下一个位置应不应该连续上,如果能连续上,让终点向后移动一位,如果不能连续上,就让下一个位置为新的起点和终点,以此类推,遍历完整个数组。那么,本题的关键就在于如何判断应不应该连续上。

五、代码讲解:

	int a[100005]={0};
	int n,j,i,k; 
	int p,q,x,y;
	int fact,sum;
	int num=1;

这部分代码是本题用到的变量,fact用来记录最后的最大的和,而sum是中间所用到的和。

	for(j=0;j<k;j++)
	{
		cin>>n;
		for(i=0;i<n;i++)
		{
			cin>>a[i];
		}
		printf("Case %d:\n",num);
		printf("%d %d %d\n",fact,p+1,q+1);
		if(j!=k-1)
		{
			printf("\n");
		}
		num++;
	}

由于本题是多组数据的输入,所以以上代码进行本道题的输入与输出。

		sum=a[0];
		fact=a[0];
		x=0,y=0,p=0,q=0;
		for(i=1;i<n;i++)
		{
			if(sum+a[i]<a[i])
			{
				sum=a[i];
				x=i;
				y=i;
			}
			else
			{
				sum=a[i]+sum;
				y++;
			}
			if(sum>fact)
			{
				fact=sum;
				p=x;
				q=y;
			}
		}

以上为本题的核心代码,(sum+a[i]<a[i])为核心判断条件,判断下一个要不要继续往下走。 如果行(sum=sum+a[i]),如果不行(sum=a[i])。每次再取sum与fact之间的最大值,最后得到的fact即为最大的和。如果一直能连续,那么起点不变,终点一直往后移,如果中间断开了,那么将起点和终点都为此位置,然后再往后找,每一次都记录起点与终点的位置,最后得到的p与q就是最后对应最大fact的起点与终点位置。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值