算法设计--最大子段和问题--动态规划
问题:给定有n个整数(包含负整数)组成的序列a1,a2,a3,......,an,求该序列子段和的最大值。
注意:当所有整数均为负值时,定义其最大字段和为0;
由bj的定义(bj是1到j位置的最大子段和:)易知,当bj-1>0时bj=bj-1+aj,否则bj=aj。
则计算bj的动态规划递归式: bj=max{bj-1+aj,aj},1≤j≤n。
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
a[i] | -2 | 11 | -4 | 13 | -5 | -2 |
b(初值=0) | -2 | 11 | 7 | 20 | 15 | 13 |
sum | 0 | 11 | 11 | 20 | 20 | 20 |
#define NUM 1001
int a[NUM];
int MaxSum(int n)
{
int sum=0;
int b=0;
for (int i=1;i<=n;i++)
{
if (b>0) b+=a[i]; else b=a[i];
if (b>sum) sum=b;
}
return sum;
}
令besti,bestj为最大子段和sum的起始位置和结束位置; 在当前位置i,如果b[i-1] ≤0时,在取b[i]=a[i] 的同时, 保存该位置i到变量begin中,显然: 当b(i-1)≤0时,begin=i; 当b(i)≥sum时,besti=begin,bestj=i。
#include<bits/stdc++.h>
using namespace std;
#define NUM 1001
int a[NUM];
int Maxsum(int n,int &besti,int &bestj)
{
int sum=0;
int b=0;
int begin=0;
for(int i=1;i<=n;i++)
{
if(b>0)b+=a[i];
else{b=a[i];begin=i;}
if(b>sum)
{
sum=b;
besti=begin;
bestj=i;
}
}
return sum;
}
int main()
{
for(int i=0;i<8;i++)
{
cin>>a[i];//1 -3 7 8 -4 12 -10 6
}
int besti=0,bestj=0;
int sum=0;
sum=Maxsum(8,besti,bestj);
cout<<sum<<endl;
cout<<besti<<" "<<bestj;
}