什么叫最大矩阵和,给你一个包含数字的矩阵,每一个矩阵格子都包含一个数字,当然有正有负,求出其所有子矩阵中最大的那个和。给定的这个矩阵也可以算一个子矩阵。
解决
1.暴力,枚举左上角的点和右下角的点,利用前缀和,然后就能求出结果,时间复杂度O(n²*n²)
2.动态规划加预处理,一维矩阵的最大连续和
我们要把二维矩阵进行降维,把二维矩阵降成一维数组
首先要知道一点,我们的最大的子矩阵,首先肯定是位于i行和j行之间的。
这里我们就需要用到一个辅助的矩阵mat[][],这个矩阵的mat[i][j]位置放置的是给定的矩阵的第j列中,前i行的所有数的和。
上面的k就是第k列,sum[k]就等于第k列中第i行和第j行之间的所有数的和,然后就能利用最大连续和求得当前矩阵的和了。
代码实现,只是实现了求出最大连续和,当前也可以实现记录最大子矩阵的位置输出最大子矩阵。
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MIN 0x80000000
#define max(x,y) x > y ? x : y
// 最大连续和
int max_sum(int* nums,int len){
int dp[len];
memset(dp,0,sizeof(dp));
dp[0] = nums[0];
int m = MIN;
for(int i=1;i<len;i++){
dp[i] = max(nums[i],nums[i]+dp[i-1]);
m = max(m,dp[i]);
}
return m;
}
int main(){
int m,n;
scanf("%d%d",&m,&n);
int map[m][n];
int table[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
scanf("%d",&map[i][j]);
if(i == 0){
table[0][j] = map[i][j];
}else{
table[i][j] = 0;
}
}
}
for(int i=1;i<m;i++){
for(int j=0;j<n;j++){
table[i][j] += map[i][j] + table[i-1][j];
}
}
int res[m];
int maxSum = MIN;
for(int i=0;i<m;i++){
for(int j=0;j<=i;j++){
for(int k=0;k<m;k++){
if(i == 0){
res[k] = table[j][k];
}else{
res[k] = table[j][k] - table[i-1][k];
}
}
int sum = max_sum(res,m);
maxSum = max(sum,maxSum);
}
}
printf("%d\n",maxSum);
}