这题的关键就是预处理矩阵利用
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i-1][j-1]
递推出矩阵,使得我们以后每次已经利用O(1)的复杂度计算任意一块矩阵
之后枚举正方形左上角的坐标二分边长,时间复杂度为n^2 log(n)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1005;
int n,m,t;
int mat[maxn][maxn];
int ans[maxn][maxn];
int get_value(int x1,int y1,int x2,int y2){
return ans[x2][y2] - (ans[x1 - 1][y2] + ans[x2][y1 - 1] - ans[x1 - 1][y1 - 1]);
}
void solve(){
int l = 1,r = min(n,m);
int rans = 0;
while(l <= r){
int h = (l + r) >> 1;
int ok = 0;
for(int i = 1; i + h - 1<= n; i++){
for(int j = 1; j + h - 1 <= m; j++){
int e = get_value(i,j,i + h - 1,j + h - 1);
if(e <= t){
ok = 1;
break;
}
}
if(ok) break;
}
if(ok){
rans = h;
l = h +1;
}
else
r = h - 1;
}
printf("%d\n",rans * rans);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(ans,0,sizeof(ans));
scanf("%d%d%d",&n,&m,&t);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d",&mat[i][j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1] + mat[i][j];
solve();
}
return 0;
}