HDU:1003 Max Sum

来源:互联网 发布:ultraedit汉化软件 编辑:程序博客网 时间:2024/05/21 07:11

最大连续子序列和的问题,之前做过好多次了。这里我用了O(n)的算法。


如果和小于0,那么再加一个元素也只会比原来的元素更小,所以不如舍去前面小于0的部分。从当前元素开始求和,同时更新起点终点为当前元素。如果和大于0,那么就加上当前元素(不必考虑当前元素的正负)(和等于0执行此步操作会使最大连续子序列更长),同时更新终点为当前元素。在这过程中更新最大值,并记录对应始末位置。

 

O(n)的算法其实是动态规划的思想。

 

      动态规划法解决最大连续子序列和    

       问题描述 :
       数组 int a[] = {-4 , 3 ,56 , -15 , 34 , 0 , -14 , 4} ; 某几个连续的子序列其和最大,比如a0+a1 = -1 。a1+a2+a3+a4 = 78 。则a1 a2 a3a4组成的数组即是所求。
      
       解决方法:
       此题尝试使用动态规划的方法进行解决,首先建立状态方程。
       设b[j]表示第j处,以a[j] 结尾的子序列的最大和。
       则b[j] = max(a[j] + b[j-1] , a[j]) ,而我们的所求的答案,就是从1- n对b数组求最大值。

       PS:其实a[j] + b[j-1] 与a[j]的比较也就是b[j-1]与0的比较。

 

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int main(){    int T,count=0;    scanf("%d",&T);    while(T--)    {    int n;    scanf("%d",&n);    int a[100010]={0};    for(int i=0;i<n;++i)scanf("%d",&a[i]);    int st=1,anst=1,ansd=1,ed=1,sum=a[0],max=a[0];    for(int i=1;i<n;++i)    {        if(sum<0)        {            sum=a[i];            st=i+1;            ed=i+1;        }        else        {            sum+=a[i];            ed=i+1;        }        if(sum>max)        {            max=sum;            anst=st;            ansd=ed;        }    }    printf("Case %d:\n",++count);    printf("%d %d %d\n",max,anst,ansd);    if(T)printf("\n");    }    return 0;}

 

 

还有用分治法来做的,我还没搞懂,先贴上代码。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define M 100005#define INF 0x7fffffffint n, a[M];int 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;    int 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;        int maxsum = solve(1,n,ansx,ansy);        printf("Case %d:\n%d %d %d\n",++k,maxsum, ansx, ansy);        if(t)  printf("\n");    }    return 0;}



 


原创粉丝点击