今天比赛的一道题目,有位同学写的代码比我写的好多了,而且有点贪心的意思,所以就贴了上来,
用sum来存前面的正和,如果sum<0的话,那么sum就置成0,意为前面的和都不要了,而重新开始找最大连续和。
这是因为前面的和小于0的话,对后面的最大连续和,做不了贡献,反而会拖了后腿。
如果现在的sum比max要大的话,则更新答案,
代码如下:
#include <cstdio>
#define M 100005
#define INF 0x7fffffff
int main ()
{
int t, n, x, start, end, sum, maxx, tt, k = 0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
start = 1; end = 1;
sum = 0; tt = 1;
maxx = -INF;
for(int i = 1; i <= n; ++i)
{
scanf("%d",&x);
sum+=x;
if(sum>maxx)
{
maxx = sum;
end = i;
start = tt;
}
if(sum<0)
{
sum = 0;
tt = i+1;
}
}
if(k) printf("\n");
printf("Case %d:\n%d %d %d\n", ++k, maxx, start, end);
}
return 0;
}
还有就是自己写的分治的代码,很长,而且不好写,,
具体思路就是入门经典上的分治法,每个区间的最大连续和或在【0......m】,或在【m+1....n】,或在【x,....m.....y】;
最后再选出最大的即可。。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 100005
#define INF 0x7fffffff
int n, a[M];
long long sum[M];
int solve(int l, int r, int &x, int &y)
{
if(l==r)
{
x = l; y = l;
return a[l];
}
int lx, ly, rx, ry;
int m = (l+r)/2;
solve(l,m,lx,ly);
solve(m+1,r,rx,ry);
int Lx = m, Rx = m+1;
long long L = -INF, R = -INF;
for(int i = m; i >= l; --i)
if(sum[m]-sum[i-1]>=L) { L = sum[m]-sum[i-1]; Lx = i; }
for(int i = m+1; i <= r; ++i)
if(sum[i]-sum[m]>R) { R = sum[i]-sum[m]; Rx = i; }
if(sum[ly]-sum[lx-1]>=sum[ry]-sum[rx-1])
{ x = lx; y = ly; }
else
{ x = rx; y = ry; }
if(L+R > sum[y]-sum[x-1])
{ x = Lx; y = Rx; }
else if(L+R == sum[y]-sum[x-1]&&Lx < x)
{ x = Lx; y = Rx; }
return sum[y]-sum[x-1];
}
int main ()
{
int t, k = 0;
scanf("%d",&t); getchar();
while(t--)
{
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
{
scanf("%d",&a[i]);
sum[i] = sum[i-1]+a[i];
}
int ansx, ansy;
long long maxsum = solve(1,n,ansx,ansy);
if(k) printf("\n");
printf("Case %d:\n%I64d %d %d\n",++k,maxsum, ansx, ansy);
}
return 0;
}