Max Sum
- 题目链接
Max Sum
- 题目大意
给你一串数,正的负的都有,现在要你算出这一列数的最大子段和(就是选取一段连续的部分,这部分所有的数加起来的和是所有情况中最大的)。
- 题解
这一题我首先想到的是用合并的方法,比如一串数,最大子段和只有可能有三种情况:
1.包含最左边的数。
2.包含最右边的数。
3.中间的某一段。
在这里,我采用递推的思路去分析1~i和1~i+1。发现第一种情况其实没必要考虑….所以在这里我们就只有2种情况要考虑了——包含最右边的情况和中间的情况。我们用max1表示中间某一段的最大子段和(就是我们的解),用max2表示包含最右边的数的最大子段和。所以在求解1~i+1的解时,我们先用max2+a[i+1],如果这个数是正数,我们就与max1比较且予以保留,如果这个数是负数,我们先比较,然后把max2清0(因为如果max2是负数的话会影响到我们后面的解,这里不太好说,具体体会吧…)
还有一点,关于很多人说这是DP,个人感觉只是一个递推而已,并没有明显的决策。
- 代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int a[100005],T,n;
int main()
{
int t;
scanf("%d",&T);
t=T;
while (T--)
{
memset(a,0,sizeof(a));
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
int max1=a[1],max2=0,s1=1,e=1,s2=1;
for (int i=1;i<=n;i++)
{
max2+=a[i];
if (max2>max1)
{
max1=max2;
s2=s1; e=i;
}
if (max2<0)
{
max2=0;
s1=i+1;
}
}
printf("Case %d:\n",t-T);
printf("%d %d %d\n",max1,s2,e);
if (T) printf("\n");
}
return 0;
}