zoukankan      html  css  js  c++  java
  • 洛谷 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
    ",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
    ",ans2);
    40     return 0;
    41 }

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

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    Linux centos 6.4安装
    vm虚拟机安装,配置与使用
    Linux简介
    360兼容视图
    补丁patch 漏洞 bug或glitch
    迫不得已! ! 仅仅针对IE浏览器的样式,尤其是IE8及以下
    JS延时器 定时器 暂停器 中断器
    CSS动态定位
    一个标准的AJAX请求
    ajax的两个重要参数contentType 和dataType
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/5808285.html
Copyright © 2011-2022 走看看