《编程之美》 2.15 子数组之和的最大值(二维)
解法一:遍历,穷举。
代码一:
int Sum(int **A, int a, int b, int c, int d)
{
int sum = 0;
int i,j,k,l;
for(i = a; i <= c; i++){
for (j = b; j <= d; j++){
sum += A[i][j];
}
}
return sum;
}
int MaxSum(int **A,int M,int N)
{
int iMin,iMax,jMin,jMax;
int sum = -INT_MAX;
int tmp;
for(iMin = 0; iMin < M; iMin++){
for(jMin = 0; jMin < N; jMin++){
for(iMax = iMin; iMax < M; iMax++){
for(jMax = jMin; jMax < N; jMax++){
tmp = Sum(A,iMin,jMin,iMax,jMax);
sum = tmp > sum ? tmp : sum;
}
}
}
}
return sum;
}
解法二:利用一维数组的DP算法,将二维看成一维来求解。
代码二:
int MaxSum2(int **A,int M,int N)
{
int maxsum = -INT_MAX;
int nStart;
int nAll ;
int tmp;
int **ps = (int **)malloc((M+1)*sizeof(int*));
for(int i = 0; i <= M; i++){
ps[i] = (int *)malloc((N+1)*sizeof(int));
}
for (int i = 0; i <= M; i++)
ps[i][0] = 0;
for (int j = 0; j <= N; j++)
ps[0][j] = 0;
for(int i = 1; i <= M; i++){
for(int j = 1; j <= N; j++){
ps[i][j] = ps[i-1][j] + ps[i][j-1] - ps[i-1][j-1] + A[i-1][j-1];
}
}
for(int a = 0; a < M; a++){
for(int c = a; c < M; c++){
nStart = ps[c+1][N] - ps[a][N] - ps[c+1][N-1] + ps[a][N-1];
nAll = ps[c+1][N] - ps[a][N] - ps[c+1][N-1] + ps[a][N-1];
for (int i = N-1; i > 0; i--){
tmp = ps[c+1][i] - ps[a][i] - ps[c+1][i-1] + ps[a][i-1];
nStart = tmp + nStart > tmp ? tmp + nStart : tmp;
nAll = nStart > nAll ? nStart : nAll;
}
maxsum = maxsum < nAll ? nAll : maxsum;
}
}
for(int i = 0; i <= M; i++){
free(ps[i]);
}
free(ps);
return maxsum;
}
测试程序:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>
void show(int **A,int M,int N);
int Sum(int **A, int a, int b, int c, int d)
{
int sum = 0;
int i,j,k,l;
for(i = a; i <= c; i++){
for (j = b; j <= d; j++){
sum += A[i][j];
}
}
return sum;
}
int MaxSum(int **A,int M,int N)
{
int iMin,iMax,jMin,jMax;
int sum = -INT_MAX;
int tmp;
for(iMin = 0; iMin < M; iMin++){
for(jMin = 0; jMin < N; jMin++){
for(iMax = iMin; iMax < M; iMax++){
for(jMax = jMin; jMax < N; jMax++){
tmp = Sum(A,iMin,jMin,iMax,jMax);
sum = tmp > sum ? tmp : sum;
}
}
}
}
return sum;
}
/*----------------------------------------------------------------------------------------*/
int MaxSum2(int **A,int M,int N)
{
int maxsum = -INT_MAX;
int nStart;
int nAll ;
int tmp;
int **ps = (int **)malloc((M+1)*sizeof(int*));
for(int i = 0; i <= M; i++){
ps[i] = (int *)malloc((N+1)*sizeof(int));
}
for (int i = 0; i <= M; i++)
ps[i][0] = 0;
for (int j = 0; j <= N; j++)
ps[0][j] = 0;
for(int i = 1; i <= M; i++){
for(int j = 1; j <= N; j++){
ps[i][j] = ps[i-1][j] + ps[i][j-1] - ps[i-1][j-1] + A[i-1][j-1];
}
}
for(int a = 0; a < M; a++){
for(int c = a; c < M; c++){
nStart = ps[c+1][N] - ps[a][N] - ps[c+1][N-1] + ps[a][N-1];
nAll = ps[c+1][N] - ps[a][N] - ps[c+1][N-1] + ps[a][N-1];
for (int i = N-1; i > 0; i--){
tmp = ps[c+1][i] - ps[a][i] - ps[c+1][i-1] + ps[a][i-1];
nStart = tmp + nStart > tmp ? tmp + nStart : tmp;
nAll = nStart > nAll ? nStart : nAll;
}
maxsum = maxsum < nAll ? nAll : maxsum;
}
}
for(int i = 0; i <= M; i++){
free(ps[i]);
}
free(ps);
return maxsum;
}
/*-----------------------------------------------------------------------------------------*/
void show(int **A,int M,int N)
{
for (int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
printf("%3d",A[i][j]);
}
printf("\n");
}
}
int main()
{
int M = 5;
int N = 6;
int **A = (int **)malloc(M*sizeof(int*));
srand(time(NULL));
for(int i = 0; i < M; i++){
A[i] = (int*) malloc(N*sizeof(int));
for (int j = 0; j < N; j++){
A[i][j] = ((rand() & 0x1) ? -1 : 1)*(rand() % 9 + 1);
}
}
show(A,M,N);
printf("Max sub sum : %d .\n",MaxSum(A,M,N));
printf("Max sub sum : %d .\n",MaxSum2(A,M,N));
for(int i = 0; i < M; i++){
free(A[i]);
}
free(A);
}
4 -5 4 5 4 6
9 1 -6 -2 2 5
-7 -3 -3 8 -8 -1
1 -6 1 7 -4 -4
5 9 4 7 4 -4
Max sub sum : 33 .
Max sub sum : 33 .
REF:
1,编程之美 2.15