zoukankan      html  css  js  c++  java
  • 51nod 1158 全是1的最大子矩阵 单调栈 / 悬线法

    题目链接:

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1158

    题意:

    给出个的矩阵,里面的元素只有0或1,找出M1的一个子矩阵,M1中的元素只有1,并且的面积是最大的。输出的面积

    题解:

    方法一: 单调栈,把每一列数看成一个数组。

    方法二: 悬线法:  http://m.blog.csdn.net/LOI__DiJiang/article/details/52813578    理论: http://www.cnblogs.com/foreverpiano/p/6924069.html

    代码:

    代码一:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 1e5+10;
    17 
    18 int a[505][505],f[505][505];
    19 
    20 struct node{
    21     int v,pre,nxt;
    22     node(int v) : v(v),pre(1),nxt(1) {}
    23 };
    24 
    25 int main(){
    26     int n,m;
    27     cin >> n >> m;
    28     for(int i=1; i<=n; i++)
    29         for(int j=1; j<=m; j++)
    30             cin >> a[i][j];
    31 
    32     MS(f);
    33     for(int i=1; i<=n; i++)
    34         for(int j=1; j<=m; j++)
    35             if(a[i][j]) f[i][j] = f[i][j-1] + 1; // 每一位置可以向左拓展几个
    36     ll ans = -1; 
    37     for(int j=1; j<=m; j++){ // 对每一列数进行一次单调栈的拓展
    38         stack<node> s;
    39         s.push(node(f[1][j]));
    40         for(int i=2; i<=n; i++){
    41             node t(f[i][j]);
    42             while(!s.empty() && t.v<=s.top().v){ // 出现比栈顶小的行数,就要弹出,因为已经不能向后拓展了
    43                 node tt = s.top(); s.pop();
    44                 if(!s.empty()) s.top().nxt += tt.nxt; // 向后拓展
    45 
    46                 t.pre += tt.pre; // 向前拓展
    47                 ll tmp = tt.v * (tt.pre+tt.nxt-1); // 计算矩形的面积
    48                 if(ans < tmp)
    49                     ans = tmp;
    50             }
    51             s.push(t);
    52         }
    53         while(!s.empty()){
    54             node tt = s.top(); s.pop();
    55             if(!s.empty()) s.top().nxt += tt.nxt;
    56             ll tmp = tt.v * (tt.pre+tt.nxt-1);
    57             if(ans < tmp)
    58                 ans = tmp;
    59         }
    60     }
    61 
    62     cout << ans << endl;
    63 
    64 
    65 
    66     return 0;
    67 }

     代码二:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 2e3+10;
    17 
    18 int n,m,a[maxn][maxn],h[maxn][maxn],l[maxn][maxn],r[maxn][maxn];
    19 
    20 int main(){
    21     cin >> n >> m;
    22     for(int i=1; i<=n; i++)
    23         for(int j=1; j<=m; j++)
    24             cin >> a[i][j];
    25 
    26     int ans = 0;
    27     for(int i=1;i<=m;++i) l[0][i]=1,r[0][i]=m;
    28     for(int i=1; i<=n; i++){
    29         int maxl=1, maxr=m;
    30         for(int j=1; j<=m; j++){
    31             if(a[i][j]==0){
    32                 h[i][j] = 0;
    33                 l[i][j] = 1;
    34                 maxl = j+1;
    35             }else{
    36                 l[i][j] = max(l[i-1][j],maxl);
    37                 h[i][j] = h[i-1][j]+1;
    38             }
    39         }
    40         for(int j=m; j>=1; j--){
    41             if(a[i][j]==0){
    42                 r[i][j] = m;
    43                 maxr = j-1;
    44             }else{
    45                 r[i][j] = min(r[i-1][j],maxr);
    46                 ans = max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);
    47             }
    48         }
    49     }
    50     cout << ans << endl;
    51 
    52     return 0;
    53 }
    54 
    55 // 3 3
    56 // 1 1 1
    57 // 1 1 0
    58 // 1 1 1
  • 相关阅读:
    学习素材、网站
    用 Python脚本生成 Android SALT 扰码
    H面试程序(29):求最大递增数
    常用数据库查询判断表和字段是否存在
    《火球——UML大战需求分析》(第3章 分析业务模型-类图)——3.7 关于对象图
    N个数依次入栈,出栈顺序有多少种
    WIN ERROR:C:WindowsSystem32<LANG_NAME>mstsc.exe.MUI
    大端法和小端法
    freopen()重定向的打开和关闭
    Linux 的 Spinlock 在 MIPS 多核处理器中的设计与实现
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827580.html
Copyright © 2011-2022 走看看