题面
题目描述
农夫约翰想要在他的正方形农场上建造一座正方形大牛棚。他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方。我们假定,他的农场划分成
N
×
N
N \times N
N×N 的方格。输入数据中包括有树的方格的列表。你的任务是计算并输出,在他的农场中,不需要砍树却能够修建的最大正方形牛棚。牛棚的边必须和水平轴或者垂直轴平行。
EXAMPLE
考虑下面的方格,它表示农夫约翰的农场,‘.'表示没有树的方格,‘#'表示有树的方格
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
1 | . | . | . | . | . | . | . |
2 | . | # | . | . | . | # | . |
3 | . | . | . | . | . | . | . |
4 | . | . | . | . | . | . | . |
5 | . | . | . | . | . | . | . |
6 | . | . | # | . | . | . | . |
7 | . | . | . | . | . | . | . |
8 | . | . | . | . | . | . | . |
最大的牛棚是 5 × 5 5 \times 5 5×5 的,可以建造在方格右下角的两个位置其中一个。
输入格式
Line 1: 两个整数:
N
(
1
≤
N
≤
1000
)
N (1 \le N \le 1000)
N(1≤N≤1000),农场的大小,和
T
(
1
≤
T
≤
10
,
000
)
T (1 \le T \le 10,000)
T(1≤T≤10,000)有树的方格的数量
Lines 2…
T
+
1
T+1
T+1: 两个整数
(
1
≤
整
数
≤
N
)
(1 \le 整数 \le N)
(1≤整数≤N), 有树格子的横纵坐标
输出格式
只由一行组成,约翰的牛棚的最大边长。
样例
输入
8 3
2 2
2 6
6 3
输出
5
解析
可以
N
2
N^2
N2枚举正方形的右下角的点
可以发现:
f
i
,
j
=
{
min
{
f
i
−
1
,
j
f
i
,
j
−
1
f
i
−
1
,
j
−
1
+
1
(
无
树
)
0
(
有
树
)
f_{i,j}=\left\{ \begin{aligned} \min\left\{ \begin{aligned} &f_{i-1,j}\\ &f_{i,j-1}\\ &f_{i-1,j-1}\\ \end{aligned} +1(无树) \right.\\ 0(有树)\\ \end{aligned} \right.
fi,j=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧min⎩⎪⎨⎪⎧fi−1,jfi,j−1fi−1,j−1+1(无树)0(有树)
代码
#include<bits/stdc++.h>
using namespace std;
int N,M;
int x,y,ans;
int a[1039][1039];
int f[1039][1039];
int min(int a,int b,int c){return (a<b&&a<c)?a:(b<c)?b:c;}
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=M;i++){scanf("%d%d",&x,&y);a[x][y]=1;}
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(!a[i][j]){f[i][j]=min(f[i-1][j],f[i][j-1],f[i-1][j-1])+1;ans=max(f[i][j],ans);}
}
}
printf("%d",ans);
}