动态规划:最大连续子段和
问题描述:
输入为两行。第一行一个整数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 }

浙公网安备 33010602011771号