维护向左,向上和向对角线扩展的最大值
然后去三个方向的最小值然后加1
************************************************************************************************
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 2510;
int a[maxn][maxn];
int dp[maxn][maxn];//在对角线方向扩展的最大1
int verti[maxn][maxn], level[maxn][maxn];//在垂直/水平方向最多扩展的0
int m, n;
int main()
{
int i, j;
scanf("%d %d", &m, &n);
memset(dp, 0, sizeof(dp));
memset(verti, 0, sizeof(verti));
memset(level, 0, sizeof(level));
int ans = 0;
//左上到右下
for(i = 1; i <= m; ++i)
for(j = 1; j <= n; ++j)
{
scanf("%d", &a[i][j]);
if(!a[i][j])
{
verti[i][j] = verti[i-1][j]+1;
level[i][j] = level[i][j-1]+1;
}
else
{
dp[i][j] = min(dp[i-1][j-1], min(verti[i-1][j], level[i][j-1]))+1;
ans = max(ans, dp[i][j]);
}
}
//右上到左下
memset(dp, 0, sizeof(dp));
memset(verti, 0, sizeof(verti));
memset(level, 0, sizeof(level));
for(i = 1; i <= m; ++i)
for(j = n; j >= 1; --j)
{
if(!a[i][j])
{
verti[i][j] = verti[i-1][j]+1;
level[i][j] = level[i][j+1]+1;
}
else
{
dp[i][j] = min(dp[i-1][j+1], min(verti[i-1][j], level[i][j+1]))+1;
ans = max(ans, dp[i][j]);
}
}
printf("%d\n", ans);
return 0;
}