zoukankan      html  css  js  c++  java
  • P1387 最大正方形

    namo题目描述

    在一个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
    分析;我们用f[i][j]表示以该点为右下角的,满足条件的,最大的正方形的边长。
      先象一下这两种情况;
      (一)如果该点的a为0,f[i][j]=0;
       (二)如果它周围的三个点中有一个是’0’,那么那个点的f[i][j]是1(构不成正方
    形)

          如果它周围的三个点都能构成正方形,那就要想想。。。
          我们从a数组上分析那么f[i][j]应该是2;
          那么,可以看出是f最小的那个点(或者说是它周围的那些点)阻碍了f[i][j]的增大。
          状态转移方程为f[i][j]=minn(f[i-1][j-1],f[i-1][j],f[i][j-1])+1;
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio> 
    #include<queue>
    #include<math.h>
    using namespace std;
    int n,m;
    int a[110][110],f[110][110],ans;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            if(a[i][j])
                f[i][j]=min(min(f[i-1][j-1],f[i-1][j]),f[i][j-1])+1;
            else f[i][j]=0;
            ans=max(ans,f[i][j]);
        }
        cout<<ans;
        return 0;
    }

     此外还有一种做法(一位同行教的),

       主体是:枚举正方形左上角的坐标,以及正方形边长。

       方法是:利用 区间和 判断是否符合。

       根据注释3,复杂度大约是n*m*log ( min(n,m) );还是比较理想的

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio> 
    #include<queue>
    #include<math.h>
    using namespace std;
    int n,m,maxn=1;
    int a[110][110],f[110][110];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)//这是个经典的二维的前缀和求法。
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];        
        }
         for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
         for(int k=maxn;i+k<n&&j+k<m;k++)//(如果在k*k的正方形区间中,区间和是边长的平方,这个区间一定是饱和的)
         {
             int w=f[i+k][j+k]+f[i][j]-f[i+k][j]-f[i][j+k];
             if(w==k*k) 
             maxn=max(maxn,k);
             else break;//如果区间中出现了一个碍事的‘0‘区间继续扩展后,一定不饱和,没必要找下去了。
         }
         printf("%d",maxn);
         return 0;
    }
  • 相关阅读:
    java.lang.NoClassDefFoundError: org/hibernate/service/ServiceRegistry] 类似问题
    哪些window你不知道的却实用的小技巧----window小技巧
    windows命令快捷启动应用-----window小技巧
    cmd窗口关闭 -----window小技巧!
    Eclipse错误笔记!
    如何在WIndows电脑上安装 SVN Server 实现代码版本控制
    linux之应用开发杂记(一)
    面试知识点汇总
    Android技术面试整理
    MYSQL常用操作语句
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/6950337.html
Copyright © 2011-2022 走看看