注解
1、dp[i],[j] 表示 以i,j为右下角,最左上方元素为左上角的矩形的元素和。(用到了前缀和的思想)
所以在输入某元素后,dp[i],[j] = dp[i],[j-1] + dp[i-1],[j] + dp[i],[j]。(其中后面这个dp[i],[j]其实指的是第(i,j)位置的元素)
2、在求出dp[i],[j]之后,要想求最大子矩阵,其实是求 dp[j],[k] - dp[j],[k-y] - dp[j-x],[k] + dp[j-x],[k-y]。其中x,y是题目输入的子矩阵规模。
代码
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 1000 + 10;
int dp[MAXN][MAXN];
int main() {
int T;
cin>>T;
for(int i=0; i<T; i++){
memset(dp, 0, sizeof(dp));
int m, n, x, y;
cin>>m>>n>>x>>y;
for(int j=1; j<=m; j++){
for(int k=1; k<=n; k++){
cin>>dp[j][k];
dp[j][k] += dp[j-1][k] + dp[j][k-1] - dp[j-1][k-1];
}
}
int ans = -1;
for(int j=x; j<=m; j++){
for(int k=y; k<=n; k++){
int tmp = dp[j][k] - dp[j][k-y] - dp[j-x][k] + dp[j-x][k-y];
if(tmp>ans){
ans = tmp;
}
}
}
cout<<ans<<endl;
}
return 0;
}