洛谷 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 }
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!