子数组之和的最大值(二维)

来源:互联网 发布:oracle数据库最高权限 编辑:程序博客网 时间:2024/05/20 02:26

《编程之美》 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 -4Max sub sum : 33 .Max sub sum : 33 .

REF:

1,编程之美 2.15 

0 0