题目大意
求一个最大为 100*100 矩阵中的子矩阵中元素之和的最大值。
思路
先考虑其一维的类似问题:最大连续子数组和问题,也就是在一个数组中找和最大的子数组,这个问题通常采用动态规划解决,状态转移方程式为,其中DP[i]表示以下标i结尾的最大连续子数组和,最终的答案是DP[0~n-1]中最大的一个。
这道题其实可以很巧妙地往一维转化。如何将二维转化为一维?将二维的其中一维固定,即我们先定下子矩阵的宽,更具体地,选定子矩阵的宽是从L行到R行,那么就可以将这些行全部加成一行,对这一行求最大连续子数组。最终从所有选法中取最大即可。
AC代码
#include<iostream>
#define INF 10000000
using std::cin;
using std::cout;
int DP(int M[][100], int l, int r, int n);
int main(){
int n;
int M[100][100];
cin>>n;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
cin>>M[i][j];
}
}
int ans = -INF, res;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
res = DP(M, i, j, n);
if(ans < res) ans = res;
}
}
cout<<ans;
return 0;
}
int DP(int M[][100], int l, int r, int n){
int d[100], dp[100];//dp[i]以i结尾的最大子段和
for(int i = 0; i < n; i++){
d[i] = 0;
for(int j = l ; j <= r; j++){
d[i] += M[i][j];
}
}
dp[0] = d[0];
for(int i = 1; i < n; i++){
dp[i] = (dp[i - 1] + d[i] > d[i] ? dp[i - 1] + d[i] : d[i]);
}
int res = -INF;
for(int i = 0; i < n; i++){
if(dp[i] > res){
res = dp[i];
}
}
return res;
}