当前位置:   article > 正文

最大子段和问题(分治法和动态规划)_最大子段和是什么意思

最大子段和是什么意思

什么是最大子段和,通俗点讲:

        最大子段和就是给了一些数,然后你从中找了几个连续的数,这组连续的数的和任意一组连续的数的和都大,那么你找的这几个连续的数的和就是这些数的最大子段和。

通俗的听不懂你就看这里:

      给定由n个整数(可能为负整数)组成的序列a_{1},a_{2}...a_{n},求该序列形如的子段和的最大值。当所有整数均为负整数时定义其最大子段和0。依此定义,所求的最优值为。例如,当(a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为 = 20。

一、分治法

分治法思想:如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情形:(不敲了。。。直接看图)

思想

  1. #include<iostream>
  2. using namespace std;
  3. int MaxSubSum(int *a,int left,int right){
  4. int sum = 0;
  5. if(left == right)
  6. sum = a[left] > 0 ? a[left] : 0;
  7. else{
  8. int center = (left + right)/2;
  9. int leftsum = MaxSubSum(a, left, center);
  10. int rightsum = MaxSubSum(a,center+1,right);
  11. int s1 = 0;
  12. int lefts = 0;
  13. for(int i =center;i>=left;i--){
  14. lefts +=a[i];
  15. if(lefts > s1)
  16. s1 = lefts;
  17. }
  18. int s2 = 0;
  19. int rights = 0;
  20. for(int j = center +1;j<=right;j++){
  21. rights += a[j];
  22. if(rights> s2)
  23. s2 = rights;
  24. }
  25. sum = s1+s2;
  26. if(sum<leftsum)
  27. sum = leftsum;
  28. if(sum<rightsum)
  29. sum = rightsum;
  30. }
  31. return sum;
  32. }
  33. int MaxSum(int n,int *a){
  34. return MaxSubSum(a,0,n);
  35. }
  36. int main(){
  37. int a[] ={-2,11,-4,13,-5,-2};
  38. cout<<"最大子段和是:"<<MaxSum(5,a)<<endl;
  39. return 0;
  40. }

二、动态规划

动态规划思想:设b[i]是以第i个数结尾的最大子段和,那么从a[i]的角度来看,b[i]的值只有两种情况,如果 b[i-1]>0,那么b[i]=b[i-1]+a[i],否则b[i]=a[i]。(我觉得这个说法比书上的好理解)。

  1. #include<iostream>
  2. using namespace std;
  3. int MaxSum(int n,int *a){
  4. int sum = 0, b = 0;
  5. for(int i =0;i<n;i++){
  6. if(b>0)
  7. b+=a[i];
  8. else
  9. b = a[i];
  10. if(b>sum)
  11. sum = b;
  12. }
  13. return sum;
  14. }
  15. int main(){
  16. int a[] = {-2,11,-4,13,-5,-2};
  17. cout<<"最大子段和:"<<MaxSum(5,a)<<endl;
  18. return 0;
  19. }

 

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号