最大连续和

给出一个长度为n的序列A1,A2,A3,...An,求最大连续和。换句话说,要求找到1=<i=<j=<n,使得Ai+...+Aj尽量大。

 

题目似乎很简单,但是在n非常大的时候(如n>10000)时,采用最习惯使用的暴力过的话似乎就有一些难度,

下面逐步给出了几种方法,解决问题在可以解出来时,应该找求最优解

 

方法一:枚举

直接在i到j之间一一枚举。复杂度O(n^3)

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a[1000],n;
 5     while(scanf("%d",&n)!=EOF)
 6     {
 7         int i;
 8         for(i=0;i<n;i++)
 9             scanf("%d",&a[i]);
10         int j,k,best=a[0];//初始化最大值
11         for(i=0;i<n-1;i++)
12             for(j=i;j<n;j++)
13             {
14                 int s=0;
15                 for(k=i;k<=j;k++)s+=a[k];
16                 if(best<s)best=s;
17             }
18         printf("%d\n",best);
19     }
20     return 0;
21 }

方法二:处理后枚举

连续子序列的和等于两个前缀和之差。复杂度O(n^2)

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int n,a[1000],s[1000];
 5     while(~scanf("%d",&n))
 6     {
 7         int i,j;
 8         for(i=0;i<n;i++)
 9             scanf("%d",&a[i]);
10         int best=a[0];
11         s[0]=0;
12         for(i=0;i<n;i++)s[i+1]=s[i]+a[i];//递归求前缀和S
13         for(i=0;i<n;i++)
14             for(j=i;j<n;j++)
15                 best=best>(s[j+1]-s[i])?best:(s[j+1]-s[i]);
16         printf("%d\n",best);
17     }
18     return 0;
19 }

方法三:分治法

划分问题:把问题实例划分为子问题

递归求解:递归解决子问题

合并问题:合并子问题的解得到原问题的解

复杂度O(nlogn)

 1 #include<stdio.h>
 2 int maxsum(int *a,int x,int y)//返回数组左闭右开区间[x,y)中最大连续和
 3 {
 4     int i,m,v,L,R,max;
 5     if(y-x==1)return a[x];//只有一个元素,直接返回
 6     m=x+(y-x)/2;//分治第一步,划分为[x,m)与[m,y)两部分
 7     int l=maxsum(a,x,m);//分治第二步,递归求解
 8     int r=maxsum(a,m,y);
 9     max=l>r?l:r;
10     v=0;L=a[m-1];//第三步,合并子问题
11     for(i=m-1;i>=x;i--){v+=a[i];L=L>v?L:v;}
12     v=0;R=a[m];
13     for(i=m;i<y;i++){v+=a[i];R=R>v?R:v;}
14     return max>(L+R)?max:(L+R);//把子问题与L和R比较
15 }
16 int main()
17 {
18     int a[1000],n;
19     while(~scanf("%d",&n))
20     {
21         int i;
22         for(i=0;i<n;i++)
23             scanf("%d",&a[i]);
24         int best=maxsum(a,0,n);
25         printf("%d\n",best);
26     }
27     return 0;
28 }

方法四:稍作处理

把O(n^2)的代码稍作处理,得到复杂度O(n)的算法

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int n,a[1000],s[1000];
 5     while(~scanf("%d",&n))
 6     {
 7         int i;
 8         for(i=0;i<n;i++)
 9             scanf("%d",&a[i]);    
10         s[0]=a[0];
11         int maxs=s[0],mins=s[0];
12         for(i=1;i<n;i++)
13         {
14             s[i]=s[i-1]+a[i];
15             maxs=maxs>s[i]?maxs:s[i];
16             mins=mins<s[i]?mins:s[i];
17         }
18         printf("%d\n",maxs-mins);
19     }
20     return 0;
21 }

 

posted @ 2013-02-12 17:25  再见~雨泉  阅读(1011)  评论(2编辑  收藏  举报