这道题是个二维数组的,我们看看:如果有一个一维数组a[n],如何找出连续的一段,使其元素之和最大呢?
例如:int a[]= {1,2, -3, 4, -2, 5,-3,-1, 7,4, -6 }; max=14。
1.穷举法(有三层循环,所以n很大时不能使用这种方法。)
int main()
{
int a[]={1 ,2, -3, 4, -2, 5 ,-3 ,-1, 7,4, -6 };
int n=11,i,j,k,max=-INF;
int sum = 0;
for(i=0; i max) max = sum;
}
}
cout<
2、带记忆的递推法
int main()
{
int a[]= {1,2, -3, 4, -2, 5,-3,-1, 7,4, -6 };
int record[20],sum=0,n=11;
int i,j,max;
record[0] = 0;
for(i=1; i<=n; i++)
record[i] = record[i-1] + a[i]; //用record记录a[i]前i个的和
max = -INF;
for(i=1; i<=n; i++)
{
for(j=0; j max) max = sum;
}
}
cout<
3、动态规划
分析一下最优子结构,若想找到n个数的最大子段和,那么要找到n-1个数的最大子段和,这就出来了。我们用b[i]来表示a[0]...a[i]的最大子段和,b[i]无非有两种情况
(1)最大子段一直连续到a[i]
(2)以a[i]为首的新的子段。
由此我们可以得到b[i]的状态转移方程:
b[i]=max{ b[i-1]+a[i],a[i] }
最终我们得到的最大子段和为max{ b[i], 0<=i 于是乎这道题中二维数组的每一列也可以看做一个一维数组。结合上面的1和3: int MaxSubArray(int a[],int n)
{
int i,b = 0,sum = 0;
for(i = 0;i < n;i++)
{
if(b>0) // 若a[i]+b[i-1]会减小
b += a[i]; // 则以a[i]为首另起一个子段
else
b = a[i];
if(b > sum)
sum = b;
}
return sum;
}
int main () {
int a[]= {1,2, -3, 4, -2, 5,-3,-1, 7,4, -6 };
int ans = MaxSubArray(a,11);
cout<
#include