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;
}
posted @ 2022-10-18 23:58  HelloHeBin  阅读(65)  评论(0)    收藏  举报