题目描述如下:
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。
要求算法的时间复杂度为O(n)。
输入格式:
输入有两行:
第一行是n值(1<=n<=10000);
第二行是n个整数。
输出格式:
输出最大子段和。
输入样例:
在这里给出一组输入。例如:
6
-2 11 -4 13 -5 -2
输出样例:
在这里给出相应的输出。例如:
20
解析:这是一道典型的动态规划问题,动态规划是当前所要解决的问题依赖于它前面的子问题,所以我们要先把子问题求解出来,才能够解决当前问题,这也就决定着我们的思路是先求解最小的子问题,自低向上的递推,直到解决问题
具体的分析已经写到注释中
#include<stdio.h>
#define MAX 1002
int main(){
int n,a[MAX];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
//--------D[i]表示的是以a[i]为终止位置的最优解-------
int D[n],max=a[0];//max=a[0]很关键,它和第18行选出最大的有关系,要不然的话,第18行只是从a[1]~a[n-1]选出最大的
D[0]=a[0];//第一个数字前面没有数字 所以以a[0]为终止位置的最优解就是它自己
for(int i=1;i<n;i++){//每一个数字都找到以它为终止位置的最优解
if(D[i-1]>0)/*如果a[i]前面的那个数字的最优解大于0,那么再加上a[i]得D[i],则D[i]就是以a[i]结
尾的所有可能中的最优解*/
D[i]=a[i]+D[i-1];
else
D[i]=a[i];/*如果a[i]前面的那个数字的最优解小于0,那么以a[i]结尾的所有可能中的最优解就是它本身*/
if(D[i]>max)
max=D[i];//选出最大的
}
for(int i=0;i<n;i++)//输出结果
printf("%d ",D[i]);
printf("\nmax is %d\n",max);
//--------D[i]表示的是以a[i]为起始位置的最优解------
D[n-1]=a[n-1];
max=a[0];
for(int i=n-2;i>=0;i--){
if(D[i+1]>0)
D[i]=a[i]+D[i+1];
else
D[i]=a[i];
if(D[i]>max)
max=D[i];
}
for(int i=0;i<n;i++)
printf("%d ",D[i]);
printf("\nmax is %d\n",max);
//不需要数组,用一个变量temp保存a[i]前面的以a[i-1]为终止最优解,这是第一种方法的简洁版
int temp=0;
max=a[0];
for(int i=0;i<n;i++){
if(temp>0)
temp+=a[i];
else
temp=a[i];
if(temp>max)
max=temp;
}
printf("max is %d\n",max);
return 0;
}