[ZJOI2007]棋盘制作

Posted charlesss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI2007]棋盘制作相关的知识,希望对你有一定的参考价值。

悬线法,用来解决给定矩阵中满足条件的最大子矩阵。

首先对于矩阵中每一个点,分别向左向右维护合法的最大范围。

之后对于每个点,与上一排比较,如果和它上方的点满足条件,就取两排中包含这两个点的最大横区间,最大纵区间递归+1.

代码如下

#include<cstdio>
#include<iostream>
#define N 2010
using namespace std;
int le[N][N],ri[N][N],up[N][N],mp[N][N],ans1,ans2;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&mp[i][j]);
            le[i][j]=ri[i][j]=j;
            up[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=2;j<=m;j++)
            if(mp[i][j]!=mp[i][j-1])
                le[i][j]=le[i][j-1];
    for(int i=1;i<=n;i++)
        for(int j=m-1;j>=1;j--)
            if(mp[i][j]!=mp[i][j+1])
                ri[i][j]=ri[i][j+1];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(i>1&&mp[i][j]!=mp[i-1][j])
            {
                le[i][j]=max(le[i][j],le[i-1][j]);
                ri[i][j]=min(ri[i][j],ri[i-1][j]);
                up[i][j]=up[i-1][j]+1;
            }
            int a=ri[i][j]-le[i][j]+1;
            int b=min(a,up[i][j]);
            ans1=max(ans1,b*b);
            ans2=max(ans2,a*up[i][j]);
        }
    printf("%d\n%d",ans1,ans2);
    return 0;
}
        

 

以上是关于[ZJOI2007]棋盘制作的主要内容,如果未能解决你的问题,请参考以下文章

[luoguP1169] [ZJOI2007]棋盘制作(单调栈)

BZOJ1057: [ZJOI2007]棋盘制作

[ZJOI2007]棋盘制作 (单调栈)

[luogu P1169] [ZJOI2007]棋盘制作

洛谷 P1169 [ZJOI2007]棋盘制作

bzoj 1057: [ZJOI2007]棋盘制作