题目描述
在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长。
输入输出格式
输入格式:
输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m个数字,用空格隔开,0或1.
输出格式:
一个整数,最大正方形的边长
输入输出样例
输入样例#1: 复制
4 4 0 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1
输出样例#1: 复制
2
怎么突然发现dp有点简单的样子...一定是错觉!!!!
这道题一个很简单的思想, 如果 当前节点的值为1的话,说明其可以组成正方形, 于是遍历左,左上,上三个节点,找到最小的点,然后就是最小的加1.如果是0说明把前面的都打乱了, 所以该点值改为0;
转移方程为
if( mp[i][j] == 1) dp[i][j] = min(dp[i-1][j], dp[i-1][j-1], dp[i][j-1]) +1;
else dp[i][j] = 0;
记录中间出现的最大值就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int mp[105][105];
int dp[105][105];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
// cout<<endl<<endl;
for(int i=0;i<=n;i++)
dp[i][0] = 0;
for(int i=0;i<=m;i++)
dp[0][i] = 0;
int tp,mx=-1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j] == 1){
tp = dp[i-1][j-1];
tp = min(tp,dp[i-1][j]);
tp = min(tp,dp[i][j-1]);
dp[i][j] = tp+1;
mx = max(mx,dp[i][j]);
}else{
dp[i][j] = 0;
}
// cout<<dp[i][j]<<" ";
}
// cout<<endl;
}
cout<<mx<<endl;
return 0;
}