动态规划:最大连续子段和

问题描述:

输入为两行。第一行一个整数n (1 <= n <= 100000), 表示一共有n个元素,第二行为n个数,每个元素每个整数都在32位int范围内。以空格分隔。输出所有连续子数组中和最大的值。

 

测试样例:

输入 3   -1 2 1   输出 3
输入 6 -2 11 -4 13 -5 -2 输出 20

算法思路:

方法1:动态规划。以 j 为下标终点,sum_max ( j ) 表示包括 x[ j ]这个数本身在内的,最大连续子段和。那么 

sum_max ( j ) = max { x[ j ], x[ j ] + sum_max( j-1 ) }.  这样动态规划的递推公式就得到了。这道题的DP矩阵是一个数组,不是一个矩阵咯,哈哈。

方法2:分治法。最大子段和有三种情况,1)在 x[1 ~ n/2 ] 中; 2)在 x[n/2+1 ~ n] 中; 3)在前2段中间。前2种情况递归即可,第3种情况,就表示 x[n/2] 和 x[n/2+1] 肯定在最大子段中,那么从这两个点出发分布向左右顺次扫描即可找出包含这2个的最大子段和。

 

方法1 C++程序:

 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 
 5 
 6 int main()
 7 {
 8     int n, tmp, max_sum, sum_before=0, sum_now=0;
 9     vector<int> vec;
10     cin>>n>>max_sum;
11     sum_before = max_sum; // first element
12     for(int i=1; i<n; i++){
13         cin>>tmp;
14         if(tmp + sum_before > tmp){
15             sum_now = tmp + sum_before;
16         }else{
17             sum_now = tmp;
18         }
19 
20         if(sum_now > max_sum){
21             max_sum = sum_now;
22         }
23         sum_before = sum_now;
24     }
25     cout<<max_sum<<endl;
26 
27     return 0;
28 }

 函数形式:

//动态规划:以终点为变量
int MIS_Dynamic(int *seq, int n)
{
    int now_sum = seq[0];
    int max_sum = now_sum;
    for(int i=1;i<n; i++){
        now_sum > 0 ? now_sum += seq[i] : now_sum = seq[i];
        if( max_sum < now_sum )
            max_sum = now_sum;
    }
    return max_sum;
}

 

方法2 C++程序:

 1 //分治法
 2 int MIS_Divide(int *seq, int l, int r)  
 3 {
 4     if( l == r )
 5         return seq[l]>0 ? seq[l] : 0;
 6     else{
 7         int center = ( l + r ) / 2;
 8 
 9         int left_sum = MIS _Divide(seq, l, center);  //最大子段和在左边序列
10         int right_sum = MIS _Divide(seq, center+1, r);  //最大子段和在右边序列
11 
12         //最大子段和中间部分,第三种情况
13         int s1 = 0;
14         int temp1 = 0;
15         for(int i=center; i>=l; i--){  //center--->左
16             temp1 += seq[i];
17             if( temp1 > s1 ) s1 = temp1;
18         }
19         int s2 = 0;
20         int temp2 = 0;
21         for(int i=center+1; i<=r; i++){  //center--->右
22             temp2 += seq[i];
23             if( temp2 > s2 ) s2 = temp2;
24         }
25         int sum = s1 + s2;
26 
27         if( sum < left_sum ) sum = left_sum;
28         if( sum < right_sum ) sum = right_sum;
29         return sum;
30     }
31 }

 

posted @ 2017-08-23 10:10  hedgehog小子  阅读(391)  评论(0)    收藏  举报