问题描述
对于给定序列a1,a2,a3……an,寻找它的某个连续子段,使得其和最大。如( -2,11,-4,13,-5,-2 )最大子段是{ 11,-4,13 }其和为20。
(1)枚举法求解
枚举法思路如下:
以a[0]开始: {a[0]}, {a[0],a[1]},{a[0],a[1],a[2]}……{a[0],a[1],……a[n]}共n个
以a[1]开始: {a[1]}, {a[1],a[2]},{a[1],a[2],a[3]}……{a[1],a[2],……a[n]}共n-1个
……
以a[n]开始:{a[n]}共1个
一共(n+1)*n/2个连续子段,使用枚举,那么应该可以得到以下算法:
具体代码如下:
算法比较简单,所以这里不一一讲解:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int MaxSum1(int n,int *a,int &besti,int &bestj)///枚举法
{
int sum=0;
for(int i=0;i<n;i++)///总共n次
{
for(int j=i;j<=n;j++)
{
int thisSum=0;
for(int k=i;k<=j;k++)
{
thisSum+=a[k];
if(thisSum>sum)
{
sum=thisSum;
besti=i;
bestj=j;
}
}
}
}
return sum;
}
int MaxSum2(int n,int *a,int &besti,int &bestj)///对枚举法的一个改进
{
int sum=0;
for(int i=0;i<n;i++)///总共n次
{
int thisSum=0;
for(int j=i;j<=n;j++)
{
thisSum+=a[j];
if(thisSum>sum)
{
sum=thisSum;
besti=i;
bestj=j;
}
}
}
return sum;
}
int MaxSum3(int n,int *a,int &besti,int &bestj)///动态规划法
{
int sum=0,b=0;
for(int i=0;i<n;i++)///总共n次
{
for(int j=i;j<=n;j++)
{
if(b>0)
{
b+=a[j];
}
else
{
b=a[j];
}
if(b>sum)
{
sum=b;
besti=i;
bestj=j;
}
}
}
return sum;
}
int main()
{
int n;
cout<<"请输入总个数n:";
cin>>n;
int a[] = {-2,11,-4,13,-5,-2};
cout<<endl<<endl<<"输出数组a为以下数:";
for(int i=0; i<n; i++)
{
cout<<a[i]<<" ";
}
int besti,bestj;
cout<<endl<<endl<<"方法MaxSum1数组a的最大连续子段和为:a["<<besti+1<<":"<<bestj+1<<"]:"<<MaxSum1(n,a,besti,bestj);
cout<<endl<<endl<<"方法MaxSum2数组a的最大连续子段和为:a["<<besti+1<<":"<<bestj+1<<"]:"<<MaxSum2(n,a,besti,bestj);
cout<<endl<<endl<<"方法MaxSum3数组a的最大连续子段和为:a["<<besti+1<<":"<<bestj+1<<"]:"<<MaxSum2(n,a,besti,bestj)<<endl<<endl<<endl;
return 0;
}
运行结果如下: