zoukankan      html  css  js  c++  java
  • bzoj1057: [ZJOI2007]棋盘制作

    dp。方型棋盘不用说,矩形棋盘每个点先维护先上能达到的最大距离v。然后dp找出以自己的v最小时向左向右能达到最大的距离l,r。

    因为最大矩形棋盘的宽度肯定等于某个点的v,我们又求出了每个v对应的最长距离(r-l+1),所以正确性得以保证。

    还有一个小技巧,把横纵坐标和为奇数的点异或。就可以把原问题转化为求最大的01矩阵了。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 2000 + 10;
    int a[maxn][maxn],f[maxn][maxn],v[maxn][maxn],l[maxn][maxn],r[maxn][maxn];
    int n,m,res1=0,res2=0;
    
    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((i+j)%2) a[i][j]^=1;
            //printf("a[%d][%d] = %d
    ",i,j,a[i][j]);
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
            if(i==1&&j==1) f[i][j]=1;
            else if(a[i][j]!=a[i][j-1] || a[i][j] != a[i-1][j]) f[i][j]=1;
            else f[i][j] = min(f[i-1][j-1],min(f[i-1][j],f[i][j-1]))+1;
            res1=max(res1,f[i][j]);
            //printf("f[%d][%d] = %d
    ",i,j,f[i][j]);
        }
        printf("%d
    ",res1*res1);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
            if(i==1) v[i][j]=1;
            else if(a[i-1][j]!=a[i][j]) v[i][j]=1;
            else v[i][j]=v[i-1][j]+1;
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
            if(j==1) l[i][j]=1;
            else if(v[i][j]>v[i][j-1] || a[i][j]!=a[i][j-1]) l[i][j]=j;
            else {
                l[i][j]=l[i][j-1];
                while(l[i][j]>1 && v[i][j]<=v[i][l[i][j]-1] && a[i][l[i][j]-1]==a[i][j]) l[i][j]=l[i][l[i][j]-1];
            }
        }
        for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--) {
            if(j==m) r[i][j]=m;
            else if(v[i][j]>v[i][j+1] || a[i][j] != a[i][j+1]) r[i][j]=j;
            else {
                r[i][j] = r[i][j+1];
                while(r[i][j]<n && v[i][j]<=v[i][r[i][j]+1] && a[i][r[i][j]+1]==a[i][j]) r[i][j]=r[i][r[i][j]+1];
            }
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) 
            res2=max(res2,v[i][j]*(r[i][j]-l[i][j]+1));
        printf("%d
    ",res2);
        return 0;
    }
  • 相关阅读:
    转自 陈皓 博客 《提高效率》
    codevs 1098 均分纸牌 2002年NOIP全国联赛提高组 x
    codevs 1160 蛇形矩阵x
    【説明する】进制转换
    欧几里得?x
    codevs 1020 孪生蜘蛛 x
    [HDOJ5883]The Best Path(欧拉回路,异或)
    [HDOJ5889]Barricade(spfa,最大流)
    [PAT L2-001] 紧急救援(spfa,最短路计数, dp)
    [CF717E]Paint it really, really dark gray(dfs,构造)
  • 原文地址:https://www.cnblogs.com/invoid/p/5426403.html
Copyright © 2011-2022 走看看