洛谷 P1387 最大正方形 Label:奇怪的解法

题目描述

在一个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

解法1

提供一种很简单的思路。要验证(i,j)能表示多大的正方形的末尾,就要验证(i-1,j)(i,j-1)(i-1,j-1)这三个点中能作为正方形末尾的最小值,然后加上一即可。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 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 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<iostream>
 6 #include<cmath>
 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<sum[i][j]-sum[i-l][j]-sum[i][j-l]+sum[i-l][j-l])
33                     {ans2=l;
34                     ans=sum[i][j]-sum[i-l][j]-sum[i][j-l]+sum[i-l][j-l];}
35                 }
36             }
37         }
38     }
39     printf("%d\n",ans2);
40     return 0;
41 }

 同类题目http://www.cnblogs.com/radiumlrb/p/5808527.html

 

posted @ 2016-08-25 20:36  Radiumlrb  阅读(797)  评论(0编辑  收藏  举报