题目描述
在一个n*m的只包含0和1的矩阵里找出一个不包含0的最大正方形,输出边长。
输入输出格式
输入格式:
输入文件第一行为两个整数n,m(1<=n,m<=100),接下来n行,每行m个数字,用空格隔开,0或1.
输出格式:
一个整数,最大正方形的边长
输入输出样例
输入样例#1:
4 40 1 1 11 1 1 00 1 1 01 1 0 1
输出样例#1:
2
解法1
提供一种很简单的思路。要验证(i,j)能表示多大的正方形的末尾,就要验证(i-1,j)(i,j-1)(i-1,j-1)这三个点中能作为正方形末尾的最小值,然后加上一即可。
代码
1 #include2 #include 3 #include 4 #include 5 #define min3(a,b,c) min(a,min(b,c)) 6 using namespace std; 7 int ans,a[1005][1005],f[1005][1005],N,M; 8 int main(){ 9 // freopen("01.txt","r",stdin);10 scanf("%d%d",&N,&M);11 for(int i=1;i<=N;i++){12 for(int j=1;j<=M;j++){13 f[i][j]=1;14 scanf("%d",&a[i][j]);15 }16 }17 18 for(int i=1;i<=N;i++){19 for(int j=1;j<=M;j++){20 f[i][j]=a[i][j]*(min3(f[i-1][j],f[i-1][j-1],f[i][j-1])+1);21 ans=max(ans,f[i][j]);22 }23 }24 25 printf("%d\n",ans);26 return 0;27 }
解法2
这个题可以应用二维数组前缀和来求解。
因为只有01这两个数,所以求前缀和会很方便的求助面积来,这样也可以很方便的找到最大边长。
注意前缀和的求法和面积的表示方法,对于二维数组的前缀和,先像一维数组那样求一遍每行的前缀和,再将每一个前缀和加上自己上面的点的前缀和。
而面积的表示:对于i,j点边长为l的正方形,前缀和表示:sum[i][j]-sum[i-l][j]-sum[i][j-l]+sum[i-l][j-l]至于为什么,大家可以自己写几组数据试试。
代码
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 int n,m,ans,ans2; 9 int mapp[105][105];10 int sum[105][105];11 int main()12 {13 scanf("%d%d",&n,&m);14 for (int i=1;i<=n;i++)15 for (int j=1;j<=m;j++)16 scanf("%d",&mapp[i][j]);17 for (int i=1;i<=n;i++)18 {19 for (int j=1;j<=m;j++)20 sum[i][j]=sum[i][j-1]+mapp[i][j];21 for (int j=1;j<=m;j++)22 sum[i][j]+=sum[i-1][j];23 }24 for (int i=1;i<=n;i++)25 {26 for (int j=1;j<=m;j++)27 {28 for (int l=1;l<=min(i,j);l++)29 {30 if(mapp[i][j]==1&&l*l==sum[i][j]-sum[i-l][j]-sum[i][j-l]+sum[i-l][j-l])31 {32 if(ans