动态规划——数组最大子数组和 收藏


问题描述:

给定一个整数数组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]。实现如下:

view plaincopy to clipboardprint?
1 #include <iostream>  
 2 using namespace std;  
 3 #define N 10   
 4 int max_sub_array(int &s,int &e,int * a)  
 5 {  
 6         int i=0;  
 7         int j =0;  
 8         int b,start,end;  
 9         int sum = 0;  
10         sum = b = a[0];  
11         s = e = start = end = 0;//s和e是整个数组a[0~n]的最大子段的起末位置。start和end是数组a[0~i]的起末位置。  
12         for(i = 1;i<N;i++)  
13         {  
14                 if(b>0)  
15                 {  
16                         b = b + a[i];  
17                         end = i;  
18                 }  
19                 else 
20                 {  
21                         b = a[i];  
22                         start = end = i;  
23                 }  
24                 if(sum<b)  
25                 {  
26                         sum = b;  
27                         s = start;  
28                         e = end;  
29                 }  
30         }  
31         return sum;  
32 }  
33 int main()  
34 {  
35         int a[N]={31,-41,59,26,-53,58,97,-93,-23,84};  
36         int start,end;  
37         int sum = max_sub_array(start,end,a);  
38         cout << sum << "  "<<start<< " "<<end<< endl;  
39 }  
 1 #include <iostream>
  2 using namespace std;
  3 #define N 10
  4 int max_sub_array(int &s,int &e,int * a)
  5 {
  6         int i=0;
  7         int j =0;
  8         int b,start,end;
  9         int sum = 0;
 10         sum = b = a[0];
 11         s = e = start = end = 0;//s和e是整个数组a[0~n]的最大子段的起末位置。start和end是数组a[0~i]的起末位置。
 12         for(i = 1;i<N;i++)
 13         {
 14                 if(b>0)
 15                 {
 16                         b = b + a[i];
 17                         end = i;
 18                 }
 19                 else
 20                 {
 21                         b = a[i];
 22                         start = end = i;
 23                 }
 24                 if(sum<b)
 25                 {
 26                         sum = b;
 27                         s = start;
 28                         e = end;
 29                 }
 30         }
 31         return sum;
 32 }
 33 int main()
 34 {
 35         int a[N]={31,-41,59,26,-53,58,97,-93,-23,84};
 36         int start,end;
 37         int sum = max_sub_array(start,end,a);
 38         cout << sum << "  "<<start<< " "<<end<< endl;
 39 } 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clearriver/archive/2009/05/29/4224154.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值