传送门(洛谷)
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为在i行j列所取得的最大值
只有
a
[
i
]
[
j
]
=
=
1
a[i][j]==1
a[i][j]==1时,节点
i
,
j
i,j
i,j才能作为正方形的右下角;
对于一个已经确定的 f [ i ] [ j ] = x f[i][j]=x f[i][j]=x,它表明包括节点 i , j 在 内 向 上 x 个 节 点 , 向 左 x i,j在内向上x个节点,向左x i,j在内向上x个节点,向左x个节点扫过的正方形中所有a值都为1;
对于一个待确定的 f [ i ] [ j ] f[i][j] f[i][j],我们已知 f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] , f [ i − 1 ] [ j − 1 ] f[i-1][j],f[i][j-1],f[i-1][j-1] f[i−1][j],f[i][j−1],f[i−1][j−1]的值,如下:
f f f数组:
? ? ? ?
? ? 2 1
? ? 3 ?
? ? ? ?
则说明原 a a a数组:
1 1 1 0
1 1 1 1
1 1 1 1
? ? ? ?
为什么要考虑
f
[
i
−
1
]
[
j
−
1
]
f[i-1][j-1]
f[i−1][j−1]呢
举个例子
1 1 1 0
1 1 0 1
1 1 1 1
1 1 1 1
在
f
[
3
]
[
4
]
f[3][4]
f[3][4]的时候边长只能为,而如果只考虑他的前一位和上一位则为二
Code:
#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define don(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=1e3+10;
int n,m;
int a[maxn][maxn],f[maxn][maxn];
template <class t> inline void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
void readdata()
{
read(n),read(m);
rep(i,1,n) rep(j,1,m) read(a[i][j]);
}
void work()
{
int ans=0;
memset(f,false,sizeof(f));
rep(i,1,n)
rep(j,1,m) {
if(a[i][j]==1)
f[i][j]=min(min(f[i-1][j],f[i][j-1]),f[i-1][j-1])+1;
ans=max(ans,f[i][j]);
}
printf("%d",ans);
}
int main()
{
freopen("input.txt","r",stdin);
readdata();
work();
return 0;
}