洛谷1169 [ZJOI2007] 棋盘制作

题目链接

题意概述:给出由0 1构成的矩阵,求没有0 1 相邻的最大子矩阵的最大子正方形。

解题思路:设f[i][j]表示i j向上能到哪,l[i][j] r[i][j]表示向左/右,转移时分开计算矩形和正方形即可。

#include<cstring>
#include<iostream>
#include<cctype>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
    register int X=0;register char ch=0;bool flag=0;
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') flag=1;
    for(;isdigit(ch);ch=getchar()) X=(X<<3)+(X<<1)+ch-'0';
    return (flag ? -X : X);
}
inline void write(int x)
{
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
const int N=2001;
int l[N][N],r[N][N],f[N][N],n,m,a[N][N],ans1=0,ans2=0;
int min(const int x,const int y){return (x < y ? x : y);}
int max(const int x,const int y){return (x < y ? y : x);}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=read(),l[i][j]=r[i][j]=(j==0 ? 1000000000 : j),f[i][j]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=2;j<=m;j++)
            if(a[i][j] != a[i][j-1])
                l[i][j]=l[i][j-1];
        for(int j=m-1;j>=1;j--)
            if(a[i][j] != a[i][j+1])
                r[i][j]=r[i][j+1];
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(i > 1 && a[i][j] != a[i-1][j])
                l[i][j]=max(l[i][j],l[i-1][j]),r[i][j]=min(r[i][j],r[i-1][j]),f[i][j]=f[i-1][j]+1;
            int k=r[i][j]-l[i][j]+1,h=min(k,f[i][j]);
            ans1=max(ans1,k*f[i][j]);
            ans2=max(ans2,h*h);
        }
    write(ans2),putchar('\n'),write(ans1);
}
View Code

 

posted @ 2018-09-04 09:32  _hcy_a  阅读(119)  评论(0编辑  收藏  举报