• 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;
    }
  • 相关阅读:
    『软件介绍』SQLServer2008 基本操作
    PCA的数学原理
    PCA的数学原理
    Oracle数据处理
    UVa 11995
    Unreal Engine 4 C++ 为编辑器中Actor创建自己定义图标
    codecombat之边远地区的森林1-11关及地牢38关代码分享
    初识ecside
    how tomcat works读书笔记 七 日志记录器
    HDU 1754(线段树区间最值)
  • 原文地址:https://www.cnblogs.com/invoid/p/5426403.html
Copyright © 2020-2023  润新知