1.1 Description
crf 拥有一个王国。
他的王国是长方形的,跨越了n 个纬度区和m 个经度区,且在每个经度区和纬度区的交界处
有一座城市(即crf 的王国一共有n m 座城市)。
某一天早上,crf 从他的一万平方米的大床上起来,他决定去视察一下他的王国,去查看一下
他的全民刷题计划的实施情况。
消息一出,全王国各城市的市长们都吓到了,因为有一些市长偷懒还没有宣布crf 的全民刷题
计划,所以全体市长集体开了个会,讨论要怎样才能让crf 不发现他们的不作为。
他们知道crf 有个坏习惯,他只会视察一个正方形区域的城市,而他们也知道视察了越多的城
市,crf 就会越开心。但一旦crf 发现他视察的城市他的政策没有贯彻下去,他就会非常愤怒,然后
把这些市长发配去养猪。
市长们现在想找出来一个最大正方形,使得在这个正方形内的所有城市都已经贯彻了crf 的全
民刷题计划。
1.2 Input
输入的第一行为两个整数n;m,表示crf 王国横跨的纬度区数量和经度区数量。
接下来n 行,每行有m 个整数,每个整数只可能为0 或者1,0 表示这个城市没有贯彻crf 的
全民刷题计划,1 表示已经贯彻。
1.3 Output
输出一个数字k,为最大的正方形的边长。
1.4 Sample
Sample Input Sample Output
3 3
0 1 1
1 1 1
1 1 1
2
1.5 Hint
对于30% 的数据,保证1≤ n,m ≤30。
对于100% 的数据,保证1≤ n,m≤ 2000。
解题思路:
首先二分边长长度为mid,n方枚举左上端点,利用二维前缀和统计以mid值为边长的正方形内0的个数,若0的个数为0,则成立,否则枚举下一个左上端点
代码如下:
#include<bits/stdc++.h> using namespace std; const int N = 2010; int n, m; int mapp[N][N]; int cnt[N][N]; inline int read(){ int x=0,f=1; char ch=getchar(); 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; } bool judge(int x){ for(int i=1; i+x-1<=n; i++) for(int j=1; j+x-1<=m; j++) if(cnt[i+x-1][j+x-1] - cnt[i+x-1][j-1] - cnt[i-1][j+x-1] + cnt[i-1][j-1] == 0) return 1; return 0; } int main(){ freopen ("inspect.in", "r", stdin); freopen ("inspect.out", "w", stdout); scanf("%d%d", &n ,&m); for(register int i=1; i<=n; i++){ for(register int j=1; j<=m; j++){ scanf("%d",mapp[i][i]); mapp[i][j]^=1; cnt[i][j] = (cnt[i-1][j] + cnt[i][j-1] - cnt[i-1][j-1] + mapp[i][j]); } } int l=0, r=2000; while(l < r){ int mid = ((l + r) >> 1) + 1; if(judge( mid ) ) l=mid; else r = mid - 1; } printf("%d", l); return 0; }