• 51Nod 1158 全是1的最大子矩阵 —— 预处理 + 暴力枚举 or 单调栈


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

    基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
     收藏
     关注
    给出1个M*N的矩阵M1,里面的元素只有0或1,找出M1的一个子矩阵M2,M2中的元素只有1,并且M2的面积是最大的。输出M2的面积。
     
    Input
    第1行:2个数m,n中间用空格分隔(2 <= m,n <= 500)
    第2 - N + 1行:每行m个数,中间用空格分隔,均为0或1。
    Output
    输出最大全是1的子矩阵的面积。
    Input示例
    3 3
    1 1 0
    1 1 1
    0 1 1
    Output示例
    4

    题解:

    POJ2559 加强版,预处理一下以每个格子作为底,最多可以往上延伸多少个格子,这样就可以把这些连续的格子看成一根柱子,如果按行枚举,那么就转化成了POJ2559的问题了,即利用单调栈,当然这题也可以直接暴力枚举。

    暴力枚举:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXM = 1e5+10;
    18 const int MAXN = 5e2+10;
    19 
    20 int a[MAXN][MAXN];
    21 int main()
    22 {
    23     int n, m;
    24     while(scanf("%d%d",&m,&n)!=EOF)
    25     {
    26         for(int i = 1; i<=n; i++)
    27         for(int j = 1; j<=m; j++)
    28         {
    29             scanf("%d",&a[i][j]);
    30             if(a[i][j]) a[i][j] += a[i-1][j];
    31         }
    32 
    33         int ans = 0;
    34         for(int i = 1; i<=n; i++)
    35         for(int j = 1; j<=m; j++)
    36         {
    37             int w = a[i][j];
    38             ans = max(ans, w*1);
    39             for(int k = j+1; k<=m; k++)
    40             {
    41                 w = min(w,a[i][k]);
    42                 ans = max(ans, w*(k-j+1));
    43             }
    44         }
    45         printf("%d
    ", ans);
    46     }
    47 }
    View Code

    单调栈:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXM = 1e5+10;
    18 const int MAXN = 5e2+10;
    19 
    20 int h[MAXN][MAXN];
    21 int Stack[MAXN][2], top;
    22 int main()
    23 {
    24     int n, m;
    25     while(scanf("%d%d",&m,&n)!=EOF)
    26     {
    27         for(int i = 1; i<=n; i++)
    28         for(int j = 1; j<=m; j++)
    29         {
    30             scanf("%d",&h[i][j]);
    31             if(h[i][j]) h[i][j] += h[i-1][j];   //预处理出高度,这样就可转化为POJ2559了
    32         }
    33 
    34         int ans = 0;
    35         for(int i = 1; i<=n; i++)
    36         {
    37             top = 0;
    38             h[i][m+1] = -1;     //在最后加个很小的值,就能把栈里的元素全部倒出来了
    39             for(int j = 1; j<=m+1; j++)
    40             {
    41                 int len = 0;    //长度
    42                 while(top && Stack[top-1][0]>=h[i][j])  //如果当前高度小于等于
    43                 {
    44                     len += Stack[top-1][1];     //长度累加
    45                     ans = max(ans,Stack[top-1][0]*len);
    46                     top--;
    47                 }
    48                 Stack[top][0] = h[i][j];    //当前元素入栈
    49                 Stack[top++][1] = len+1;    //把出栈了的元素的长度都累加到入栈元素当中去
    50             }
    51         }
    52 
    53         printf("%d
    ", ans);
    54     }
    55 }
    View Code
  • 相关阅读:
    HDU4507 吉哥系列故事――恨7不成妻(数位dp)
    UCF Local Programming Contest 2017 G题(dp)
    ICPC Latin American Regional Contests 2019 I题
    UCF Local Programming Contest 2017 H题(区间dp)
    HDU2089 不要62
    AcWing1084 数字游戏II(数位dp)
    UCF Local Programming Contest 2017 F题(最短路)
    Google Code Jam 2019 Round 1A Pylons(爆搜+贪心)
    AcWing1083 Windy数(数位dp)
    Vue
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8759490.html
Copyright © 2020-2023  润新知