P1387 最大正方形
最大正方形
题目描述
在一个 \(n\times m\) 的只包含 \(0\) 和 \(1\) 的矩阵里找出一个不包含 \(0\) 的最大正方形,输出边长。
输入格式
输入文件第一行为两个整数 \(n,m(1\leq n,m\leq 100)\),接下来 \(n\) 行,每行 \(m\) 个数字,用空格隔开,\(0\) 或 \(1\)。
输出格式
一个整数,最大正方形的边长。
样例 #1
样例输入 #1
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
样例输出 #1
2
分析
- 法1:二分答案,注意边界。
- 法2:dp,定义 f[i][j] 表示以 (i,j) 作为右下角的最长正方形边长,画图找转移方程。
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m,f[N][N],ans=0;
bool check(int k) {
for(int i=k; i<=n; i++) {
for(int j=k; j<=m; j++) {
int cnt=f[i][j]-f[i-k][j]-f[i][j-k]+f[i-k][j-k];
if(cnt>=k*k) return 1;
}
}
return 0;
}
void slove1() { // 二分答案
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
int l=0, r=max(n,m);
while(l<r) {
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
ans=l;
}
void slove2() { // dp
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if(f[i][j]) f[i][j]=min(min(f[i-1][j-1],f[i-1][j]),f[i][j-1])+1;
ans=max(ans,f[i][j]);
}
}
}
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++) cin>>f[i][j];
slove1();
// slove2();
cout<<ans;
return 0;
}

浙公网安备 33010602011771号