zoukankan      html  css  js  c++  java
  • 1159 最大全0子矩阵

    /*
    f(i,j)表示以(i,j)为右下角的最大全0子矩阵的边长
    若a[i][j]==1,f(i,j)=0
    否则:f(i,j)=min{ f(i-1,j),f(i,j-1),f(i-1,j-1) }+1
    这样求得的是最大全0正方形子矩阵
    要求长方形矩阵,上述思路行不通
    假设以(i,j)为右下角的最大矩阵=12
    它可能是3*4、4*3、2*6、6*2、1*12、12*1
    按上述思路进行状态转移的话,取得最优值的方案不唯一时,
    所有的方案需要都记下,用于后续的状态转移。

    在长方形全0子矩阵中,考察某个位置(i,j)
    在第i行中,包含(i,j)位置的全0区间长度>=长方形的宽
    若第i行是子矩阵的最后一行,由(i,j)位置向上,连续0的个数>=长方形的高
    设[l(i,j)..r(i,j)]是第i行上包含(i,j)的全0子区间
    第i1行到第i2行且包含(i2,j)的子矩阵需满足的条件:
    (i1..i2,j)均为0,i2-i1+1=矩阵的高
    (i,j)对应的区间[l(i,j)..r(i,j)]>=矩阵的宽
    孤立地计算l(i,j)、r(i,j),再枚举i1,i2,j,时间复杂度O(n^3)
    l(i,j)与l(i,j-1),r(i,j)与r(i,j+1)之间有关系;
    定义h(i,j)表示位置(i,j)向上连续0的个数,h(i,j)与h(i-1,j)之间有关系;
    矩形的宽取决于[i1..i2]行中第j列上[l(i,j)..r(i,j)]的最小值
    定义l(i,j),r(i,j)分别表示截止到第i行,之前的h(i,j)行中,全0元素的左右区间,
    那么子矩阵的大小=(r(i,j)-l(i,j)+1)*h(i,j)
    h(i,j)的递推关系
    if(a[i][j]==0) h(i,j)=h(i,j)+1;

    else h(i,j)=0;
    l(i,j)的递推关系
    定义mx表示之前0出现的左侧位置,初始值=1
    if(a[i][j]==0){
    l(i,j)=max(l(i-1,j),mx); //mx的值不变 
    }else{ //a[i][j]===1,此时的h(i,j)=0,不存在包含(i,j)的子矩阵 
    mx=j+1; l(i,j)=1; 
    }
    r(i,j)的递推关系
    定义mn表示之前0出现的右侧位置,初始值=n
    if(a[i][j]==0){
    r(i,j)=min(mn,r(i-1,j))
    }else{
    mx=j-1; r(i,j)=n;
    }
    其中l(i,j),r(i,j),h(i,j)都可以压缩成一维数组。 
    */

     1 #include <cstdio>
     2 #include <iostream>
     3 using namespace std;
     4 const int maxn=2010;
     5 int n,a[maxn],l[maxn],r[maxn],h[maxn];
     6 int mx,mn,ans;
     7 int main()
     8 {
     9     scanf("%d",&n);
    10     for(int col=1;col<=n;col++)
    11       l[col]=r[col]=col;
    12     for(int row=1;row<=n;row++)
    13     {
    14         mx=1; mn=n;
    15         for(int col=1;col<=n;col++)
    16         {
    17             scanf("%d",&a[col]);
    18             if(a[col]==0)
    19               h[col]=h[col]+1;
    20             else
    21               h[col]=0;
    22             if(a[col]==1)
    23               mx=col+1;
    24             if(a[col]==0)
    25               l[col]=max(l[col],mx);
    26             else
    27               l[col]=1;
    28         }
    29         for(int col=n;col>0;col--)
    30         {
    31             if(a[col]==1)
    32               mn=col-1;
    33             if(a[col]==0)
    34               r[col]=min(r[col],mn);
    35             else
    36               r[col]=n;
    37             ans=max(ans,h[col]*(r[col]-l[col]+1));
    38         }
    39     }
    40     printf("%d
    ",ans);
    41     return 0;
    42 }



  • 相关阅读:
    Sql Server 日期时间格式转换
    Windows7中pagefil.sys和Hiberfil.sys文件删除与转移
    64位机的pl/sql不安装32位oracle的连接方式
    cmd下进入oracle sqlplus
    杂七杂八
    做题记录Ⅱ
    SPOJ GSS8
    AGC036 A-Triangle | 构造
    Atcoder 题目泛做
    CF398A Cards | 贪心
  • 原文地址:https://www.cnblogs.com/lutongxi/p/5371095.html
Copyright © 2011-2022 走看看