代码改变世界

动态规划求最大子序列和

2009-10-06 14:07  诸葛二牛  阅读(527)  评论(0编辑  收藏  举报
问题描述:

有一串数字(可正可负的int,放在数组Num里),要求找到起始位置start和终止位置end,使得从start位置到end位置的所有数字之和最大,返回这个最大值max。

最简单的方法是用动态规划算法实现:
设 f[x] 为以 a[x] 终止且包含 a[x] 的最大序列的和,有:
f[1] = a[1];
f[x+1] = f[x] > 0 ? f[x] + a[x+1] : a[x+1]
那么最大子序列的和就是 f[1] .. f[n] 中最大的一个。

算法的时间复杂度为O(n),代码实现如下:


#define MaxSize 10000 +10
int k,max,s,e,cmax,cs,ce;
int nums[MaxSize];

void ready()
{
    
int i;
    max 
= nums[1];
    s 
= 1
    e 
= 1;
    
for( i=1; i<=k; i++)
        
if(max < nums[i]) 
        { 
            max 
= nums[i];
            s 
= i; 
            e 
= i;
        }

}
void compute()
{
     
// 求数组nums[]中连续子序列的最大和,并标出该子序列
    
// 设 f[x] 为以 a[x] 终止且包含 a[x] 的最大序列的和,有:
    
//    f[1] = a[1];
    
//    f[x+1] = f[x] > 0 ? f[x] + a[x+1] : a[x+1]
    
// 那么最大子序列的和就是 f[1] .. f[n] 中最大的一个
    int i,j;
    
if( max <0return;
    cmax 
= nums[1];
    cs 
= 1;
    ce 
= 1;
    
for( i=2; i<=k ; i++)
        
if(cmax >0)
        {
            cmax
+= nums[i];
            ce 
= i;
            
if( cmax > max) 
            {
                max 
= cmax;
                s 
= cs;
                e 
= ce;
            }
        }
        
else
        {
            cmax 
= nums[i];
            cs 
= i;
            ce 
= i;
        }
}

 

void MaxSubseq_DP(int nums[], int count, int &resStart, int &resEnd, int &resMax)
{
    
// 求数组nums[]中连续子序列的最大和,并标出该子序列
    
// 设 f[x] 为以 a[x] 终止且包含 a[x] 的最大序列的和,有:
    
//    f[1] = a[1];
    
//    f[x+1] = f[x] > 0 ? f[x] + a[x+1] : a[x+1]
    
// 那么最大子序列的和就是 f[1] .. f[n] 中最大的一个
    int start, max;
    
int i;
    
    start 
= resStart = resEnd = 0//初始化当前子序列和最大子序列为nums[0]
    max = resMax = nums[0];

    
for (i = 1; i < count; ++i) {
        
if (max > 0{
            max 
+= nums[i];
        }
 else {
            max 
= nums[i]; //抛弃当前子序列
            start = i; //开始新的子序列搜索
        }

        
        
if (resMax < max) //更新最大子序列
            resMax = max;
            resStart 
= start;
            resEnd 
= i;
        }

    }
//for

    
return;
}