题意
简单来说,就是给你一个0/1矩阵,让你找这样一个正方形:一条对角线全是1,其他地方全是0,并使得这个矩阵的边长最大
solution
- 考虑维护一个s1[i][j]表示从(i,j)开始,往上连续0的长度,s2[i][j]表示向左的
- 这样向左斜的就这样
f[i][j]=min(f[i-1][j-1],min(s1[i-1][j],s2[i][j-1]))+1;
- 向右斜的同理
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
inline int read(){
char ch=' ';int f=1;int x=0;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=3000;
int f[N][N];
int s1[N][N];// up
int s2[N][N];
int a[N][N];
int main()
{
int n,m;
n=read();m=read();
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
a[i][j]=read();
}
}
int ans=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(!a[i][j])
{
s1[i][j]=s1[i-1][j]+1;
s2[i][j]=s2[i][j-1]+1;
}
else
f[i][j]=min(f[i-1][j-1],min(s1[i-1][j],s2[i][j-1]))+1;
ans=max(ans,f[i][j]);
}
}
memset(s1,0,sizeof(0));
memset(s2,0,sizeof(0));
memset(f,0,sizeof(f));
for(i=1;i<=n;i++)
{
for(j=m;j>=1;j--)
{
if(!a[i][j])
{
s1[i][j]=s1[i-1][j]+1;
s2[i][j]=s2[i][j+1]+1;
}
else
{
f[i][j]=min(f[i-1][j+1],min(s1[i-1][j],s2[i][j+1]))+1;
}
ans=max(ans,f[i][j]);
}
}
cout<<ans<<endl;
return 0;
}