zoukankan      html  css  js  c++  java
  • 转载:最大子段和问题(Maximum Interval Sum)

    一.问题描述
     
          给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大.或者求出最大的这个和.
          例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4].
          如果该序列的所有元素都是负整数时定义其最大子段和为0。
     
     二. 问题分析
          1、最大子段和问题的简单算法:
     
     
     
     
          2、最大子段和问题的分治法:
     
          求子区间及最大和,从结构上是非常适合分治法的,因为所有子区间[start, end]只可能有以下三种可能性:
          在[1, n/2]这个区域内
          在[n/2+1, n]这个区域内
          起点位于[1,n/2],终点位于[n/2+1,n]内
     1 int DAC(int * array, int left, int right)
     2 {
     3     if (left == right)
     4         return array[left]>0 ? array[left] : 0;
     5 
     6     int center = ( left + right ) / 2;
     7     int leftSum = DAC(array, left, center);
     8     int rightSum = DAC(array, center+1, right);
     9 
    10     int temp = 0;
    11     int leftHalfMaxSum = 0;    
    12     for (int i=center;i>=left;--i)
    13     {        
    14         temp += array[i];
    15         if (leftHalfMaxSum < temp)
    16             leftHalfMaxSum = temp;
    17     }
    18     temp = 0;
    19     int rightHalfMaxSum = 0;
    20     for (int i=center+1;i<=right;++i)
    21     {
    22         temp += array[i];
    23         if (rightHalfMaxSum  < temp)
    24             rightHalfMaxSum = temp;
    25     }
    26 
    27     int max = leftSum > rightSum ? leftSum : rightSum;
    28     return max > leftHalfMaxSum + rightHalfMaxSum ? max : leftHalfMaxSum + rightHalfMaxSum;
    29 }

         分治法的难点在于第三种情形的理解,这里应该抓住第三种情形的特点,也就是中间有两个定点,然后分别往两个方向扩张,以遍历所有属于第三种情形的子区间,求的最大的      一个,如果要求得具体的区间,稍微对上述代码做点修改即可. 分治法的计算时间复杂度为O(nlogn).

        3、最大子段和问题的动态规划算法:
          令b[j]表示以位置 j 为终点的所有子区间中和最大的一个
          子问题:如j为终点的最大子区间包含了位置j-1,则以j-1为终点的最大子区间必然包括在其中
          如果b[j-1] >0, 那么显然b[j] = b[j-1] + a[j],用之前最大的一个加上a[j]即可,因为a[j]必须包含
          如果b[j-1]<=0,那么b[j] = a[j]。
     
          对于这种子问题结构和最优化问题的证明,可以参考算法导论上的“剪切法”,即如果不包括子问题的最优解,把你假设的解粘帖上去,会得出子问题的最优化矛盾.证明如下:
          令a[x,y]表示a[x]+…+a[y] , y>=x
          假设以j为终点的最大子区间 [s, j] 包含了j-1这个位置,以j-1为终点的最大子区间[ r, j-1]并不包含其中
          即假设[r,j-1]不是[s,j]的子区间
          存在s使得a[s, j-1]+a[j]为以j为终点的最大子段和,这里的 r != s 
          由于[r, j -1]是最优解, 所以a[s,j-1]<a[r, j-1],所以a[s,j-1]+a[j]<a[r, j-1]+a[j]
          与[s,j]为最优解矛盾.
     1 int DP(int *a, int size)
     2 {
     3     int *b = new int[size];
     4     b[0] = a[0];
     5     int max = b[0];
     6     for (int i=1;i<size;++i)
     7     {
     8         if (b[i-1] > 0)
     9             b[i] = b[i-1] + a[i];
    10         else
    11             b[i] = a[i];
    12 
    13         if(b[i]>max)
    14             max = b[i];
    15     }
    16     return max;
    17 }

    测试代码:

     1 #include "stdafx.h"
     2 #include <stdlib.h> 
     3 #include "DivideAndConquer.h"
     4 #include "DynamicProgramming.h"
     5 
     6 
     7 int _tmain(int argc, _TCHAR* argv[])
     8 {
     9     int array[] = {-2, 11, -4, 13, -5, -2};
    10     //int result = DAC(array, 0, 5);
    11     int result = DP(array, 6);
    12     printf("%d", result);
    13     system("pause");
    14     return 0;
    15 }

    转自:http://blog.csdn.net/jiyanfeng1/article/details/8058604

  • 相关阅读:
    http://www.kankanews.com/ICkengine/archives/18078.shtml
    c# ArrayList 的排序问题!
    MVC各种传值方式
    MVC3学习第五章 排山倒海第一变母版页,模型
    MVC3学习第三章 剑出鞘之前奏控制器,URL路由
    MVC3学习第二章 剑出鞘之看剑vs2010安装MVC3和建立你的第一个MVC3项目
    MVC3学习第四章 剑出鞘之后续MVC3的新特性之Razor视图解析
    MVC3学习第一章 掀起它的盖头来
    有关匿名函数执行与传参
    ubuntu12.04安装jdk7u79linuxi586.tar.gz
  • 原文地址:https://www.cnblogs.com/kira2will/p/3464192.html
Copyright © 2011-2022 走看看