在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长。
Input
输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m个数字,用空格隔开,0或1.
Output
一个整数,最大正方形的边长
Sample 1
Inputcopy Outputcopy
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
2
分析:dp:开两个for循环遍历,记录当前可以组成正方形的最大边长,每次比较遍历位置的 正左 正上 左上位置中最小的再加1,如果三个位置都不为0,可以找最小的加1,很奇怪但就是这样,正方形的原因吧
AC代码;
#include <bits/stdc++.h>
using namespace std;
int a[110][110],sum[110][110];
int main()
{
int n,m,ans;
ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]==1)
{
sum[i][j]=min( min(sum[i-1][j],sum[i][j-1]),sum[i-1][j-1] )+1;
}
else sum[i][j]=0;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
ans=max(ans,sum[i][j]);
}
cout<<ans<<endl;
}
二维前缀和:
#include <bits/stdc++.h>
using namespace std;
int n,m,ans,tot,cnt;
int s[101][101],ma[101][101],sum[101][101];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>ma[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[i][j]=ma[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];//前缀和
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int p=i,q=j,tmp=1;//(p,q)为起点 逐步扩展
if(ma[p][q]==1 && sum[p][q]-sum[i-1][q]-sum[p][j-1]+sum[i-1][j-1]==tmp*tmp && p<=n&&q<=m)
{
while(ma[p][q]==1&&sum[p][q]-sum[i-1][q]-sum[p][j-1]+sum[i-1][j-1]==tmp*tmp && p<=n&&q<=m)
p++,q++,tmp++;
ans=max(ans,p-i);
}
}
printf("%d\n",ans);
}