最大子段和问题—分治法


一、问题描述

简述

给定有n个整数(可能为负整数)组成的序列a1,a2,...,an,求该序列连续的子段和的最大值。 如果该子段的所有元素和是负整数时定义其最大子段和为0。

Input

第一行有一个正整数n(n<1000),后面跟n个整数,绝对值都小于10000。直到文件结束。

Output

输出它的最大子段和。

输入

6 -2 11 -4 13 -5 -2

输出

20

二、解题思路

分支法基本思想

将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

解题思路

  1. 对于数组的最大子段和问题,它最大子段要么在左半边,要么在右半边,要么是穿过中间,三种情况
  2. 每次把N个字段在中间分成两段用递归直至字段分解成长度为一时在返回数组下标对应的数
  3. 每次递归得到左半边和右半边的最大字段后再求穿过中间的情况对应的最大子段,三者取最大值

三、代码

#include <iostream>
#include <math.h>
using namespace std;

int *p;
int f(int l,int r){
    if(l==r)
        return p[r];
    int mid = (l + r)/2;
    int t1 = f(l,mid);
    int t2 = f(mid+1,r);

    int maxl=0,maxr=0;
    int sum = 0;
    for(int i=mid;i>=l;i--){
        sum+=p[i];
        if(sum>maxl)
            maxl = sum;
    }
    sum = 0;
    for(int i=mid+1;i<=r;i++){
        sum+=p[i];
        if(sum>maxr)
            maxr = sum;
    }
    return max(max(t1,t2),maxl+maxr);
}

int main()
{
    int n;
    cin>>n;
    p = new int[n];
    for(int i=0;i<n;i++){
        cin>>p[i];
    }
    int res = f(0,n-1);
    cout<<res<<endl;

    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM