zoukankan      html  css  js  c++  java
  • BZOJ 1057 棋盘制作(最大01相间子矩阵)

    求最大01相间子矩阵可以转换为求最大全0子矩阵。只需把棋盘(x+y)为奇数的取反,而该问题可以用经典的悬线法O(n^2)的求解。

    悬线法呢。

    首先定义b[i][j],为a[i][j]向上的最大连续0的长度。可以O(n^2)递推求出。

    l[i][j],为b[i][j]向左边的最大连续序列的长度,该连续序列满足b[i][k]<=b[i][j]. r[i][j]同理。

    那么以该点a[i][j]拓展的最大全0子矩阵即为 b[i][j]*(l[i][j]+r[i][j]+1).

    最大全0子正方形则取两者的min值相乘即可。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-9
    # define MOD 12345678
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=2005;
    //Code begin...
    
    int a[N][N], b[N][N], l[N][N], r[N][N], ans1, ans2, n, m, st[N], head;
    
    void sol()
    {
        FOR(i,1,n) FOR(j,1,m) b[i][j]=(a[i][j])?0:b[i-1][j]+1;
        FOR(i,1,n) {
            head=0; st[head]=0;
            FOR(j,1,m) {
                while (head>0&&b[i][st[head]]>=b[i][j]) --head;
                l[i][j]=j-st[head]-1; st[++head]=j;
            }
            head=0; st[head]=m+1;
            for (int j=m; j>=1; --j) {
                while (head>0&&b[i][st[head]]>=b[i][j]) --head;
                r[i][j]=st[head]-j-1; st[++head]=j;
            }
            FOR(j,1,m) {
                ans1=max(ans1,min(b[i][j],l[i][j]+r[i][j]+1)*min(b[i][j],l[i][j]+r[i][j]+1));
                ans2=max(ans2,b[i][j]*(l[i][j]+r[i][j]+1));
            }
        }
    }
    int main ()
    {
        scanf("%d%d",&n,&m);
        FOR(i,1,n) FOR(j,1,m) {
            scanf("%d",&a[i][j]);
            if ((i+j)&1) a[i][j]^=1;
        }
        sol();
        FOR(i,1,n) FOR(j,1,m) a[i][j]^=1;
        sol();
        printf("%d
    %d
    ",ans1,ans2);
        return 0;
    }
    View Code
  • 相关阅读:
    python开源项目聚合推荐【1】
    python开发--Python实现延时操作的几种方式
    odoo开发笔记 -- 单台物理服务器上,利用docker部署多套odoo应用
    odoo开发笔记 -- odoo官方docker启动原理
    odoo开发笔记 -- odoo官方docker镜像部署
    odoo开发笔记 -- 借助模块queue_job实现异步方法调用
    odoo开发笔记 -- 提高访问安全性的一种方式
    python开发笔记-pymsslq连接操作SqlServer数据库
    运维笔记--Debian/Ubuntu系统离线安装pymssql,连接SqlServer
    python开发笔记-str转字典
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6502206.html
Copyright © 2011-2022 走看看