最大序列片断和

最大序列片断和
 
定义1 对于一个序列A={a1,a2,…,an} 来说,其片断和S[i] [j] = ∑ak | i <= k <= j。
那么有了片断和的定义,片断和又怎么求呢?先来看一个基本的题目:
 
例题1
题目描述
给出一个序列A={a1,a2,…,an},求它的最大片断和。
输入
输入第一行为一个整数n(1<=n<=1000000),第二行包含n个整数。这n个整数的和的绝对值不超过2^31。
输出
一个整数为序列A的最大片断和。这个题目我想大家已经都不陌生了。解决的方法是用贪心。我还是小说一下。
假设我们要的最大片断和为S[i][j] (i < j )。那么我们保证不会存在S[i] [k] < 0 ( k < j )。因为如果存在这样的情况,那么片断和S[k + 1] [j] = S [i] [j] – S [i] [k] > S [i] [j]。和假设矛盾。
在下面的算法中,如果存在了一段S[i] [k] < 0 ,我们肯定不会用这段,将其舍掉。下面的算法中不会出现S [p] [k] > 0 ( p < i )。所以算法是正确的。
 
最大片断和的求法(源程序) #include <iostream>
 
int     N , MaxSegment;
int     Num [1000000];
main ()
{
        using namespace std;
        int     i , Part;
 
        for ( cin >> N , i = 0; i < N; i ++ ) cin >> Num [i];
        MaxSegment = 0x80000000;
        for ( Part = 0 , i = 0; i < N; i ++ ) {
                Part += Num [i];
                if ( Part > MaxSegment ) MaxSegment = Part;
                if ( Part < 0 ) Part = 0;
        }
        cout << MaxSegment;
        system ( "pause" );
}
然后我们看下一个例题(PKU2479)。
 
例题2
题目描述
给出一个序列A={a1,a2,…,an},如下定义一个函数d(A):
                     t1     t2         
d(A) = max{ ∑ai + ∑aj | 1 <= s1 <= t1 < s2 <= t2 <= n }
          i=s1   j=s2                     
你的任务就是计算d(A )。
输入
第一行是测试数据组数T(<=30)。然后是T组测试数据。每组数据包含一个整数n(2<=n<=50000)。第二行包含n个整数a1, a2, ..., an. (|ai| <= 10000)。之后是一行空行。
输出
每组数据一个整数d(A)。各占一行。
    简单的说,就是求两段不相交的片断和最大是多少。有两种解决办法:第一种仍然沿用贪心策略。第二种用动态规划方法解决。
因为这两个最大的片断一定会和单个最大片断有关。我们可以求出最大片断并记录最大片断所在的位置。然后有两部分:第一,求出除了这个最大片断以外的剩余部分中的最大片断,两者加和;第二,将这个最大片断分成两份(就是在最大片断中找出一段部分和最小的部分,和求部分和类似)。贪心的效率为O(n)。
第二种方法是DP。用MaxSegment1[i] 表示以子序列{a1,a2,…,ai}的最大片断和。这个在上面的过程中记录一下即可。
用MaxSegment2 [i]表示以ai结尾的两段子序列的最大和,那么规划方程为:
MaxSegment2 [i] = Max { MaxSegment2 [i – 1] , MaxSegment1 [i – 1]} + ai | ( i > 2 , MaxSegment2 [i] = a1 + a2 )}
这里ai有两种选择,要么独立一个片断MaxSegment1[i – 1] + ai,要么与前面的ai-1一起组成一个片断(MaxSegment2 [i – 1] + ai)。
时间复杂度为O(n)。
 
接下来你一定发现,这个DP方法的扩展性非常的好,它可以应用到多个片断。假设我们要求一个序列的M不相交片断和的最大值,甚至可以用MaxSegment[i] [j] 表示前j个数以aj结尾的最大i片断和。然后对上面的递推做适当的修改即可。时间复杂度为O(n×m)。
下面的题目就是这样的一个题,如果有时间不妨试一下:
http://acm.hziee.edu.cn/showproblem.php?pid=1024
posted @ 2008-12-04 12:39  jesonpeng  阅读(180)  评论(0编辑  收藏  举报