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

    原题链接:https://www.luogu.org/problem/show?pid=1387

    理论上来说可以暴力枚举边长和右下角坐标,而且似乎有人能用这方法过这道题。。。

    不过枚举太不现实,而且数据强一点的话就彻底没办法了,还是要DP。

    用两个数组l,w分别存储每个位置(包括本身)向左和向上各有几个连续的1,如果一个位置是1,这个位置的w和l就能从别的位置转移过来。(似乎预处理能与输入一起完成?不过我没这么做。)

    然后对f数组进行处理,对于每一个正方形,我们都可以把它看作是一层一层的,像这样:

    第一层:

    1

    第二层:

    0 1

    1 1

    第三层:

    0 0 1

    0 0 1

    1 1 1

    如果能构成正方形,那么前面的几层都必须是完整的。对于每一个a[i][j]==1的位置,f[i][j]的取值为f[i-1][j-1]+1,l[i][j]与w[i][j]的最小值

    插一句,luogu上数据略水,处理f的时候把m写成n居然都有90分。。。

    #include<cstdio>
    void read(int &y)
    {
        y=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9')
        {
            y=y*10+x-'0';
            x=getchar();
        }
    }
    int n,m,a[105][105],ans;
    int f[105][105],l[105][105],w[105][105];
    int min(int x,int y)
    {
        if(x<y) return x;
        else return y;
    }
    int main()
    {
        read(n);read(m);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++) read(a[i][j]);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]==1)
                {
                    w[i][j]=w[i-1][j]+1;
                    l[i][j]=l[i][j-1]+1;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]==1)
                {
                    f[i][j]=min(min(w[i][j],l[i][j]),f[i-1][j-1]+1);
                    if(ans<f[i][j]) ans=f[i][j];
                }
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    多线程GCD(二)
    多线程
    Runtime & Runloop
    MTK android 重启测试脚本
    ubuntu samba 配置简介
    Gerrit使用简介
    MTK andorid从底层到上层添加驱动
    MTK GPIO 新增变量配置
    MT6755 使用R63350 IC 出现唤醒概率性闪白,并导致ESD FAIL
    android L版本AAL新架构
  • 原文地址:https://www.cnblogs.com/zeroform/p/7566589.html
Copyright © 2011-2022 走看看