您的位置:首页 > 其它

数组最大子数组和(续)之动态规划

2014-03-19 15:28 204 查看
前景介绍:

之前我们一直使用枚举法求和,这是我们的新方法--动态规划。

问题描述:

给定一个整数数组a[0~n],求数组a的子数组,使其元素和为最大。

问题分析:

方法一:可以用普通的方法枚举所有的子数组,然后求出最大的子数组和,时间复杂度为O(n*n)。

方法二:问题描述符合动态规划最优子结构的要求。

设b[i]表示以a[i]结尾 的子数组的最大子段和,即:

b[i]=max{sum(a[j~k])},其中0<=j<=i,j<=k<=i。

因此对于数组a[0~n]的最大字段和为max{b[i]},其中0<=i<n。

在计算b[i]时,可以考虑以下三种情况:

1,b[i] = b[i-1]+a[i],当b[i-1]>0时,这时候的b[i]中包含a[i]。

2,b[i] = a[i],当b[i-1]<=0,这时候以a[i]重新作为b[i]的起点。

3,b[i]不包含a[i]的情况,这种情况在计算b[i]之前已经计算处结果,保存在b[0~i-1]中。最后计算max{b[i]}时会考虑到。

b[i] = max{ b[i-1]+a[i],a[i]}。

而数组a[0~n]则为max{b[i]}。

在实现时,可以省略数组b[i]。实现如下:

#include <iostream>
using namespace std;
#define N 10
int max_sub_array(int &s,int &e,int * a)
{
int i=0;
int j =0;
int b,start,end;
int sum = 0;
sum = b = a[0];
s = e = start = end = 0;//s和e是整个数组a[0~n]的最大子段的起末位置。start和end是数组a[0~i]的起末位置。
for(i = 1;i<N;i++)
{
if(b>0)
{
b = b + a[i];
end = i;
}
else
{
b = a[i];
start = end = i;
}
if(sum<b)
{
sum = b;
s = start;
e = end;
}
}
return sum;
}
int main()
{
int a
={31,-41,59,26,-53,58,97,-93,-23,84};
int start,end;
int sum = max_sub_array(start,end,a);
cout << sum << "  "<<start<< " "<<end<< endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: