方法一,穷举法(思考过程照片记录):
程序子数组中变量示图:
程序代码:
1 #include<stdio.h> 2 #define M 5 3 #define N 5 4 int sum(int a[][N],int iu,int id,int jl,int jr) //求以 iu,id,jl,jr 为顶点的子数组的和 5 { 6 int s=a[iu][jl]; 7 int i,j; 8 for(i=iu;i<=id;i++) 9 { 10 for(j=jl;j<=jr;j++) 11 { 12 if((i==iu)&&(j==jl)) 13 { 14 continue; 15 } 16 s+=a[i][j]; 17 } 18 } 19 return s; 20 } 21 void main() 22 { 23 int a[M][N]={0,-1,2,-2,-2,-3,1,2,3,5,8,2,-6,9,-3,-1,2,3,9,3,5,6,-3,-7,-4};
24 int i_up,i_down,j_left,j_right; 25 int s,max=a[0][0]; 26 int i,j; 27 for(i_up=0;i_up<M;i_up++) //子数组矩形块左上顶点 28 { 29 for(i_down=i_up;i_down<M;i_down++) //子数组矩形块右上顶点 30 { 31 for(j_left=0;j_left<N;j_left++) //子数组矩形块左下顶点 32 { 33 for(j_right=j_left;j_right<N;j_right++) //子数组矩形块右下顶点 34 { 35 s=sum(a,i_up,i_down,j_left,j_right); //求子数组和 36 if(max<s) 37 max=s; 38 } 39 } 40 } 41 } 42 printf("数组为: "); //输出数组 43 for(i=0;i<M;i++) 44 { 45 for(j=0;j<N;j++) 46 { 47 printf("%d ",a[i][j]); 48 } 49 printf(" "); 50 } 51 printf("最大子数组和为%d ",max); //输出最大子数组的值 52 }
方法二:
自《编程之美》学习思路方法:
时间复杂度 O(M^2*N^2)
原数组B[M+1][N+1],数字存储从下标1开始,将B[i][0]和B[0][j]都初始化为0,方便计算。
初始化PS[M+1][N+1]数组:PS[i][0]和PS[0][j]也初始化为0,PS[M+1][N+1]用来存储以B[1][1]为左上角,右下角任意的矩形元素和。
for(i=0;i<=M;i++)
PS[i][0]=0;
for(j=0;j<=N;j++)
PS[0][j]=0;
for(i=1;i<=M;i++)
for(j=1;j<=N;j++)
PS[i][j]=PS[i-1][j]+PS[i][j-1]-PS[i-1][j-1]+B[i][j];
利用PS数组依次比较每个子数组的大小。
for(i_min=1;i_min<=M;i_min++)
for(i_max=i_min;i_max<=M;i_max++)
for(j_min=1;j_min<=N;j_min++)
for(j_max=j_min;j_max<=N;j_max++)
{ sum=PS[i_max][j_max]-PS[i_min][j_max]-PS[i_max][j_min]+PS[i_min][j_min];
if(max<sum)
max=sum;
}