给定n个整数组成的序列:a0,a1,....,an,求该序列的子字段和的最大值。
例如当啊a[]={-1,11,-4,13,-3,-2},时最大字段和为20。
1、简单算法:
void MaxSumSimple(int n,int *a) //简单算法
{
int sum=0,tempSum=0;
int endp,start; //结束、开始位置
int i=0,j=0;
for(i=0;i<n;i++)
{
tempSum=0; //每次计算一个子段都要先将临时和置零
for(j=i;j<n;j++)
{
tempSum+=a[j];
if(tempSum>sum)
{
sum= tempSum;
start=i;
endp=j;
}
}
}
printf("%d %d %d",sum,start,endp);
}
2、动态规划:
void MaxLocationAndSum(int n,int *a) //动态规划
{
int sum=0,b=0;
int endp,start; //结束、开始位置
int i;
for(i=0;i<n;i++)
{
if(b>0) b+=a[i];
else b=a[i];
if(b>sum)
{
sum=b;
endp=i;
}
}
printf("最大子段和 :%d\n",sum);
printf("结束位置 :%d\n",endp);
sum=0,b=0;
for(i=endp;i>=0;i--)
{
if(b>0) b+=a[i];
else b=a[i];
if(b>sum)
{
sum=b;
start=i;
}
}
printf("开始位置 :%d\n",start);
}
3、分治法:
int MaxSumP(int *a,int left,int right)
{
int i;
int sum=0;
if(left==right)
{
sum=a[left]>0?a[left]:0;
}
else
{
int center=(left+right)/2;
int leftsum=MaxSumP(a,left,center);
int rightsum=MaxSumP(a,center-1,right);
int s1=0;
int lefts=0;
for(i=center;i>left;i--)
{
lefts+=a[i];
if(lefts>s1)
{
s1=lefts;
}
}
int s2=0;
int rights=0;
for(i=center+1;i<right;i++)
{
right+=a[i];
if(rights>s2)
{
s2=rights;
}
}
sum=s1+s2;
if(sum<leftsum) sum=leftsum;
if(sum<rightsum) sum=rightsum;
}
return sum;
}