通过这个题学习了一下最大连续和这一块,这个题有好几种方法的,
一种是http://blog.csdn.net/shuangde800/article/details/7828614用的:
“最大连续和问题,有好几种算法,其中最快的一种是O(n)的,只需要扫描一遍即可。
假设用数组arr存好感度 , 那么设sum[i]=arr[0]+arr[1]+..+arr[i]. 即sum[i]是从车站1到车站i的好感度之和。 这样的话,如果要求某一段车站的好感度之和, 假设车站3到车站5,只需要O(1)时间: sum[5]-sum[2]就是答案。 要使得sum[i]-sum[j]更大,就要使得sum[j]更小。因而不断更新sum[min],然后一次判断sum[i]-sum[min]和max做题时需要注意的是,答案要求好感度最大的连续和区间长度越长越好, 起点越早越好。”代码如下:
#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
//freopen("in.txt","r",stdin);
int cas,r,num[20002],left,right;
scanf("%d",&cas);
for(int cass=1; cass<=cas; cass++)
{
scanf("%d",&r);
num[0]=0;
for(int i=1; i<=r-1; i++)
{
scanf("%d",&num[i]);
num[i]+=num[i-1];
}
int min=0,max=-2147483647;
for(int i=1; i<=r-1; i++)
{
int t=num[i]-num[min];
if(t>max)
{
max=t;
left=min;
right=i;
}
else if(t==max)
{
if(min==left)
right=i;
else if(i-min>right-left)
{
right=i;
left=min;
}
}
if(num[i]<num[min])
min=i;
}
if(max>0)
cout<<"The nicest part of route "<<cass<<" is between stops "<<left+1<<" and "<<right+1<<"\n";
else cout<<"Route "<<cass<<" has no nice parts\n";
}
return 0;
}
第二种就是
http://blog.csdn.net/frankiller/article/details/8074741,不需要像上述代码一样num[i]+=num[i-1],
从左到右逐步累加,记录每次累加之后的最大值,假如累加值<0,则将累加值清0,重新累加。当这个过程结束之后所记录的最大值就是最大的连续序列的累加值。因为只需要从左到右扫描一次,因此算法的复杂度为O(n),代码如下:
#include<stdio.h>
#include<string.h>
int main()
{
int a[20001],n,i,j,max,begin,start,end,f,s,sum;
scanf("%d",&sum);
for (j=1; j<=sum; j++)
{
scanf("%d",&n);
f=1;
for (i=1; i<n; i++)
{
scanf("%d",&a[i]);
if (a[i]>0) f=0;
}
if (f) printf("Route %d has no nice parts\n",j);
else
{
s=0;
max=0;
start=1;
begin=1;
end=1;
for (i=1; i<n; i++)
{
s=s+a[i];
if (s<0)
{
s=0;
start=i+1;
}
if (s>max ||((s==max)&&(i-start>end-begin)))
{
max=s;
begin=start;
end=i;
}
}
printf("The nicest part of route %d is between stops %d and %d\n",j,begin,end+1);
}
}
return 0;
}
另外,lrj书上有一个分治法。还需要深刻理解。