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;
    }
    
  • 相关阅读:
    [转]Cordova + Ionic in Visual Studio
    [转]Getting Start With Node.JS Tools For Visual Studio
    TypeScript
    [转]NPOI TestFunctionRegistry.cs
    [转]Cordova android框架详解
    [转]POI : How to Create and Use User Defined Functions
    [转]用NPOI操作EXCEL--通过NPOI获得公式的返回值
    [转]Formatting the detail section to display multiple columns (水晶报表 rpt 一页多列)
    [转]Creating Mailing Labels in SQL Server Reporting Services (rdlc 数据1页 2竖排 显示)
    [转]Tetris(俄罗斯方块) in jQuery/JavaScript!
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9164705.html
Copyright © 2011-2022 走看看