题目链接
解题思路:
动态规划,二维前缀和(相关知识可以看OI-Wiki关于前缀和这一部分知识)。
a[i][j]是输入的矩阵,res[i][j]表示以点i,j为右下角的点能够构成的最大正方形的边长。
当a[i][j]==1时,点i,j才能作为正方形的右下角;
对于一个已经确定的res[i][j]=x,它表明包括节点i,j在内向上和向左扫过的x个点所构成的正方形中所有的a值都为1;
可以当作先看向上和向左扫最多到多少,即取二者最小值min(res[i-1][j],res[i][j-1]),然后看左上角点是否可行即min(min(res[i-1][j],res[i][j-1]),res[i-1][j-1])然后+1是本身自己这个点。
所以可以写出状态转移方程如下:
if(a[i][j]==1) res[i][j]=min(min(res[i-1][j],res[i][j-1]),res[i-1][j-1])+1;
给个例子体会下:
原矩阵
a[i][j]:
0 0 0 1
1 1 1 1
0 1 1 1
1 1 1 1
结果矩阵
f[i][j]:
0 0 0 1
1 1 1 1
0 1 2 2
1 1 2 3
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int a[105][105],res[105][105];
int main(){
int n,m,ans=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==1) res[i][j]=min(min(res[i-1][j],res[i][j-1]),res[i-1][j-1])+1;
ans=max(ans,res[i][j]);
}
}
printf("%d\n",ans);
return 0;
}