zoukankan      html  css  js  c++  java
  • P4147 玉蟾宫 (单调栈)

    题目背景

    有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。

    题目描述

    这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。

    现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。

    但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。

    输入输出格式

    输入格式:
    第一行两个整数N,M,表示矩形土地有N行M列。
    接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。


    输出格式:
    输出一个整数,表示你能得到多少银子,即(3*最大'F'矩形土地面积)的值。

    输入输出样例

    输入样例#1:
    5 6
    R F F F F F
    F F F F F F
    R R R F F F
    F F F F F F
    F F F F F F


    输出样例#1:
    45

    说明

    对于50%的数据,1<=N,M<=200

    对于100%的数据,1<=N,M<=1000

    Solution

    模板最大子矩阵...
    这道题需要用到一个东西,叫做单调栈.于是乎就在这里做一个补充.


    首先,我们需要将这个问题转换一下:
    图中是一个 4×6 的矩形,画出红色的是我们要找到的区域。

    然后我们可以将这个图转化:
    因为我们要找的是矩形,所以它一定是以 某个行元素开始的,如果枚举行的时候,我们会发现:

    对于第一行:

    对于第二行:

    第三行:

    第四行: 

    那么我们原始矩形可以变成如下的形式的数据:


    然后此时的话,就是给你若干个柱状图,然后要你求其中的最大矩形: ![](https://images2018.cnblogs.com/blog/1277344/201806/1277344-20180610221715632-461351500.gif)

    那么明显是可以 n^2 枚举的,但是这样会爆.
    那么怎样才能在 O(n) 的时间复杂度下处理出这个东西呢?
    我们使用单调栈.


    单调栈,顾名思义,就是里面元素满足单调性质的一个栈.因为我们可以很容易推出来,当我们一个矩形的高度可以计算的时候,选择的区域里面所有条状的高度都要大于等于当前这个高度.


    然后我们看具体操作:
    一个 L 数组 ,代表当前这个高度,我们可以达到的最左边的点.
    一个 R 数组 ,同理.
    我们需要遍历两遍,一遍处理当前的 L 数组.一遍处理 R 数组.


    1)先将一个 (0,0) 的元素推进栈中.
    2)每一次我们遍历到的点就是我们现在要处理的.
    3)先一直把栈中高于当前选择的节点的高度的点都弹出.
    (这个应该很好理解.因为只有低于我的点才是边界).
    4)如果栈已经空了,就把 L [ i ] 赋成 1.
    5)否则,则赋成当前的栈顶+1 (栈顶已经小于我们了).


    然后的话 R 数组是一样的处理方式.
    然后每一次的以当前我们的高度处理出来的最大面积就是:

    [height[i]×(R[i]-L[i]+1) ]

    然后统计答案即可.


    然后这道题题目就用这个模板处理出来每一行即可.

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1008;
    int c[maxn][maxn];
    int n,m,ans=-1;
    int a[maxn][maxn];
    
    int pre(int x,int y)
    {
        if(x>n)return 0;
        if(c[x][y]==1)a[x][y]=1;
        pre(x+1,y);
        if(a[x][y])
        a[x][y]+=a[x+1][y];
        return a[x][y];
    }
    
    void getans(int x)
    {
        stack<int>s;
        int l[maxn]={0},r[maxn]={0};
        for(int i=1;i<=m;i++)
        {
            while(s.size()&&a[x][s.top()]>=a[x][i]) 
            s.pop();
            if(s.empty()) l[i]=1;
            else l[i]=s.top()+1;
            s.push(i);
        }
        while(!s.empty()) s.pop();
        for(int i=m;i>=1;i--)
        {
            while(s.size()&&a[x][s.top()]>=a[x][i]) 
            s.pop();
            if(s.empty()) 
            r[i]=m;
            else 
            r[i]=s.top()-1;
            s.push(i);
        }
        while(!s.empty()) s.pop();
        for(int i=1;i<=m;i++)
        {
            int num=a[x][i]*(r[i]-l[i]+1);
            ans=max(num,ans);
        }
    }
    
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            char ch;
            cin>>ch; 
            if(ch=='R')c[i][j]=0;
            else c[i][j]=1;	
        }
        for(int i=1;i<=m;i++)
        pre(1,i);
        for(int i=1;i<=n;i++)
        getans(i);
        cout<<ans*3<<endl;
        return 0;
    }
    
  • 相关阅读:
    Android的数据存储
    Servlet第一天
    JavaScript高级程序设计读书笔记(3)
    Interesting Papers on Face Recognition
    Researchers Study Ear Biometrics
    IIS 发生意外错误 0x8ffe2740
    Father of fractal geometry, Benoit Mandelbrot has passed away
    Computer vision scientist David Mumford wins National Medal of Science
    Pattern Recognition Review Papers
    盒模型bug的解决方法
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9164705.html
Copyright © 2011-2022 走看看