问题描述 给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。 其中,A的子矩阵指在A中行和列均连续的一块。 输入格式 输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。 接下来n行,每行m个整数,表示矩阵A。 输出格式 输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。 样例输入 3 3 -1 -4 3 3 4 -1 -5 -2 8 样例输出 10 样例说明 取最后一列,和为10。 数据规模和约定 对于50%的数据,1<=n, m<=50; 对于100%的数据,1<=n, m<=500,A中每个元素的绝对值不超过5000。
代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define N 500 5 6 int main(void) 7 { 8 int i,j,k,max,sum; 9 int n,m; 10 int dp[N+1][N+1]; 11 12 memset(dp,0,sizeof(dp)); 13 scanf("%d%d",&n,&m); 14 for (i=1 ; i<=n ; i++) 15 { 16 for (j=1 ; j<=m ; j++) 17 { 18 scanf("%d",&k); 19 dp[i][j] = dp[i-1][j] + k;//预处理:同一列中,前i行的和 20 } 21 } 22 23 max = -0x3f3f3f3f; 24 for (i=1 ; i<=n ; i++)//确定起始行:i 25 { 26 for (j=i ; j<=n ; j++)//确定终止行:j 27 { 28 sum = 0; 29 for (k=1 ; k<=m ; k++)//计算j-i行,最大k段和 30 { 31 if (sum >= 0) 32 sum += dp[j][k]-dp[i-1][k]; //累加k段和 33 else 34 sum = dp[j][k]-dp[i-1][k]; //获得当前位置的值 35 36 max = max>sum?max:sum; 37 } 38 } 39 } 40 printf("%d",max); 41 42 return 0; 43 }
解题思路:
关于类似求连续子序列和的问题,可以参考:https://www.cnblogs.com/woxiaosade/p/10327587.html
本题涉及到通过动态规划压缩矩阵,从而变成求最大连续子序列和的问题;
1.首先对记录的数据做预处理,即每次计算同一列下,前n行的和 : dp[ i ][ j ] = dp[ i-1 ][ k ] + 录入值;
2.预处理完毕,即完成了对矩阵压缩成一维数组的操作,然后开始遍历 m 个数字,计算对应的最大连续和