最大子段和
问题描述:
给定由n个整数(包含负整数)组成的序列a1,a2,...,an,求该序列子段和的最大值。
当所有整数均为负值时定义其最大子段和为0。
依此定义,所求的最优值为:
例如,当(a1,a2 , a3 , a4 , a5 ,a6)=(-2,11,-4,13,-5,-2)时,
最大子段和为:
11+(-4)+13 =20
解: 最大字段和:
一层循环:动态规划,循环从0~n-1,代表最大子段和的字段的结束位置。使用temp作为当前和的暂定值,
如果temp+a[i]<0则代表最大字段的开始位置可能从i开始,但也有可能不是,
当temp>sum的时候,做交换。
二层循环:第一层循环代表字段的开始位置,第二层循环代表字段的结束位置,temp标记依次加a[j]
当temp>sum时候,就交换,并且记住当前的i和j,作为起始位置
三层循环:暴力寻找, 第一层循环代表字段的开始位置,第二层循环代表字段的结束位置,第三层循环做相应的加法
#include <stdio.h>
int n;
int a[100];
void first()
{//一层循环
int sum=0;
int temp=0;
for(int i=0;i<n;i++)
{
if(temp + a[i]<0){
temp=0;
}
else
temp+=a[i];
if(temp>sum){
sum=temp;
}
}
printf("%d\n",sum);
}
void second()
{//两层循环
int sum=0;
int ii,jj;
for(int i=0;i<n;i++)
{
int temp=0;
for(int j=i;j<n;j++)
{
temp+=a[j];
if(temp>sum){
sum=temp;
ii=i;jj=j;
}
}
}
printf("%d->%d\n",ii,jj);
printf("%d\n",sum);
}
void third()
{//三层循环
int sum=0;
int ii,jj;
for(int i=0;i<n-1;i++)
{
for(int j=i;j<n;j++)
{
int temp=0;
for(int k=i;k<=j;k++)
{
temp+=a[k];
}
if(temp>sum){
sum=temp;
ii=i;jj=j;
}
}
}
printf("%d->%d\n",ii,jj);
printf("%d\n",sum);
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
printf("one:\n");
first();
printf("two:\n");
second();
printf("three:\n");
third();
return 0;
}