最大字段和这是动态规划的经典问题,上一讲我们讲了一个简单的动态规划问题,这个最大子段和也不难,我们主要通过这几个简单的问题来了解一下动态规划。还有最大子段和用分治法也能做,等到日后我们在讲。
问题描述:给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。
当所给的整均为负数时定义子段和为0。
解决思路:
之前说个,动态规划解决问题是自底向上。原问题的规模是n个元
素。这n个元素不好考虑,我们先考虑n-1个元素,这样还不好考
虑,我们考虑n-2个元素,这样依次递减,最后问题规模变成一个
元素。但是我们发现,在递减的过程中间,子问题的最优解包含
在原问题的最优解之中,而且子问题的解还有一些是重复的。
因此,使用动态规划来解决这个问题。
就像上一篇博客中讲到的,我们要写出一个递归方程。我们设置一个数组b来存放最优解,首先将b[1]=a[1],a存放的是我们的n个元素。第i个元素,他的状态就是将他放不放到数组b中(和之前的有些像)。因此,递归方程就是:b[i]=max{b[i-1]+a[i],a[i]}.
例如:
有一组数
,
如
-2 5 4 -3 7
的最大子段和是
13,
是从
5
到
7.
代码:
#include <stdio.h>
#define N 100
int a[N];
int main()
{
int i,n,b[N],max;
while(scanf("%d",&n)&&n!=0)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=a[1];
for(i=2;i<=n;i++)
{
if(b[i-1]>0)
b[i]=b[i-1]+a[i];
else
b[i]=a[i];
}
max=b[1];
for(i=1;i<=n;i++)
if(max<b[i])
max=b[i];
printf("%d\n",max);
}
return 0;
}
在这里,我们如果要求输出是那些数,我们该怎么办??
我们只需要在设置一个数组c,来存放是那些书构成了最大子段和。当将i放入b中的时候,我们就将对应的i放入c,最后输出c就可以了。代码就不写了,望各位自己实现!