zoukankan      html  css  js  c++  java
  • 最长子序列问题之系列一

       求解最大连续子序列和问题,最直接的办法就是求出每个连续子序列的和,然后找出最大和即可,但这种算法的效率为O(n^2),代码如下,

    int LS()
    {
    int Max=-999999999;
    for( int i=0;i<n;i++)
    {
    int sum=0;
    for( int j=i;j<n;j++)
    {
    sum
    +=a[j];
    if(sum>Max) Max=sum;
    }
    }
    return Max;
    }

     这种算法适用于数据量比较小的情况。

       在这种方法里, 有许多不必要的重合计算,而正是这些不必要的计算影响了程序的执行效率。为了提高算法的效率,尽可能的排除那些不必要的计算过程,可以采用一下算法,此算法效率为O(n).

      此算法的改进之处就在于消除了前一个算法出现多次重复的弊端。


    //该算法满足连续子序列求和问题:sum>=0的情况
    //如果有最大和为负数的情况,可以以特殊情况单独处理即可
    for(i=0;i<n;i++)
    {
    cin
    >>a[i];
    sum
    +=a[i];
    if(sum>Max)
    {
    Max
    =sum;
    start
    =k+1;
    end
    =i+1;
    }
    if(sum<0)//关键点,消除不必要的重复
    {
    k
    =i+1;
    sum
    =0;
    }
    }

     算法思想:

        对于每个a[i]而言,在和前一次的sum相加后都会进行一次比较, 

      if(sum>Max)
       {
        Max=sum;
        start=k+1;
        end=i+1;
       } , 其中start记录最大连续子序列的起始位置,end记录其结束位置 ,而在如果出现sum<0的情况 ,直接将sum=0; 因为对于任何一个子序列来说,在保证了其sum>=0的前提下,出现负数是不可能的,故可将其直接清0;而此时需对起始位置进行记录,以便下一次如果出现sum>Max的情况,则可为start重新赋值。 

          此处还有一个需要注意的地方就是0<sum<Max的情况,其实这也好理解,如果0<sum<Max, 则继续执行 sum+=a[i], 在这种情况下不能对sum进行清0,因为sum是一个递增的过程,可能在某一时刻会出现sum>Max的情况。

    做题的时候碰到了两种情况:

    (1)http://acm.hdu.edu.cn/showproblem.php?pid=1003  上面的过程就是解决这个问题的

    (2)http://acm.hdu.edu.cn/showproblem.php?pid=1231 

     因为上面的出现保证了sum>=0的情况,所以 对上面的算法做一个小处理就ok了,处理如下:

    1.   排除都为负数的情况
    2.   排除最大和为0的情况

    代码如下,

       
    for(i=0;i<n;i++)
    {
    cin
    >>a[i];
    if(a[i]<0) count++; //排除都为负数的情况
    if(a[i]==0&&i<L) L=i; //排除最大和为0的情况
    sum
    +=a[i];
    if(sum>Max)
    {
    Max
    =sum;
    start
    =k+1;
    end
    =i+1;
    }
    if(sum<0)
    {
    k
    =i+1;
    sum
    =0;
    }
    }
    if(Max>0) cout<<Max<<" "<<a[start-1]<<" "<<a[end-1]<<endl;
    else if(count!=n&&Max==0) cout<<Max<<" "<<a[L]<<" "<<a[L]<<endl;
    else cout<<Max<<" "<<a[0]<<" "<<a[n-1]<<endl;

      

  • 相关阅读:
    BZOJ1443 [JSOI2009]游戏Game
    BZOJ4950 [Wf2017]Mission Improbable
    假期编程
    假期编程
    假期编程
    假期编程
    假期编程练习-求和
    假期编程练习——一个数的n次幂取余
    假期编程练习———十进制转二进制
    小球抛物线运动
  • 原文地址:https://www.cnblogs.com/FCWORLD/p/2016417.html
Copyright © 2011-2022 走看看