一、题目
一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。
二、解题思路
这题是最大子段和的二维推广,实质可以将二维进行枚举,并化为最大子段和求解。最后子矩阵一定是在某两行之间的。因此假设
我们认为子矩阵在第i行和第j行之间,我们如何得到i和j呢,可以进行枚举。 枚举所有1<=i<=j<=M,表示最终子矩阵选取的行范围。
然后对每一种i,j行间选定后对列用最大子段和处理(可以想象成将矩阵的 i 行到 j 行进行压缩成一行后对这一行进行最大字段和求解)。
三、代码
#include <iostream>
using namespace std;
int main (){
int m, n; // m行n列
cin>>m>>n;
int a[m+1][n+1];
int t;
for(int i = 1; i<=n; i++) a[0][i] = 0; // 第0行填0
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++){
cin>>t;
a[i][j] = a[i-1][j] + t;
}
int b[n+1]; // 记录每一轮的最大子段和
int Max = a[1][1]; // 记录最大子矩阵和
for(int i=1; i<=m; i++){
for(int j=i; j<=m; j++){
b[1] = a[j][1] - a[i-1][1]; // 第一个数复制
Max = max(Max, b[1]);
for(int k=2; k<=n; k++){
b[k] = max(b[k-1] + a[j][k] - a[i-1][k], a[j][k] - a[i-1][k]); // 每一轮的最大子段和算法
if(b[k] > Max) Max = b[k]; // 更新总的最大子矩阵和
}
}
}
cout<<Max<<endl;
return 0;
}