问题
给定由n个整数(包含负整数)组成的序列a1,a2,…,an,求该序列子段和的 最大值。当所有整数均为负值时定义其最大子段和为0。
**举个栗子:**当(a1,a2, a3, a4, a5,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为:11-4+13=20
一个简单算法
我们可通过循环来找到最大的和
当字段的开始下标确定后,若 要计算[i:j]的字段和可以利用 上一次计算的[i:j-1]的字段
改进
我们发现这个题可以用分治来进行
分治算法
如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和 a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段 和有三种情形:
A. a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;
B. a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;
C. a[1:n]的最大子段和为下面的形式。
得到下面算法
动态规划算法
bj表示从a1到aj(前 j 项)中,包含aj的最大的子段和
由bj的定义易知,当bj-1>0 时bj=bj-1+aj,否则bj=aj。
由此可得计算bj的动态规划递归式bj=max{bj-1+aj,aj},1≤j≤n。
代码实现
#include<stdio.h>
int main()
{
int a[101];
int sum,i,n,b=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]); //输入数据
}
for(i=1;i<=n;i++){
if(b<0){
b=a[i];
}else{
b+=a[i];
}
if(sum<b) {
sum=b;
}
}
printf("%d\n",sum);
return 0;
}