[LUOGU] P1387 最大正方形

题目描述
在一个n*m的只包含01的矩阵里找出一个不包含0的最大正方形,输出边长。

输入输出格式
输入格式:
输入文件第一行为两个整数n,m1<=n,m<=100),接下来n行,每行m个数字,用空格隔开,01.

输出格式:
一个整数,最大正方形的边长

输入输出样例
输入样例#1: 
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
输出样例#1: 
2

首先想到O(n^3)的做法 f[i][j][k] 以(i,j)为左上角边长为k符合的正方形
可以由内部四个k-1边长的正方形转移
年前考试就用了O(n^3)的,T了几个点

#include<iostream>
using namespace std;

bool f[105][105][105];
int n,m;
int ans=1;

int main() {
    cin>>n>>m;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            cin>>f[i][j][1];
        }
    }
    for(int k=2; k<=max(n,m); k++) {
        for(int x=1; x<=n; x++) {
            for(int y=1; y<=m; y++) {

                f[x][y][k]=
                    f[x][y][k-1]&
                    f[x+1][y][k-1]&
                    f[x][y+1][k-1]&
                    f[x+1][y+1][k-1];
//              cout<<x<<" "<<y<<" "<<k<<" "<<f[x][y][k]<<endl;
                if(f[x][y][k]) ans=max(ans,k);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

然后有O(n^2)的做法

f[i][j] 以(i,j)为右下角点的最大符合的正方形边长

可以由左、上、左上最小值转移来

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
using namespace std;

const int MAXN=105;

bool a[MAXN][MAXN];
int f[MAXN][MAXN];
int n,m;

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
        }
    }
    int ans=-233;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]==0) continue;
            f[i][j]=min(f[i-1][j],min(f[i][j-1],f[i-1][j-1]))+1;
            ans=max(ans,f[i][j]);
        }
    }
    cout<<ans<<endl;
    return 0;
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247470.html

原文地址:https://www.cnblogs.com/ghostcai/p/9247470.html