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

    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

    这是一道非常经典的题目。看到学长们个个都用悬线法来做,无奈本蒟蒻水平过低,只会用单调栈来切这道题。

    我们可以把F看做1,R看做0。

    来看下面这个矩阵:

    看起来这道题似乎无从下手,但是如果我们把每一列1的连续和求出来,像这样:

    也许我们仍然没能发现什么规律,但是不要紧,我们接着看:

                  

           

    我们尝试以每一行作为这个矩形的底边,找出图中最大的矩形,也就是图中的染色部分,有没有想起点什么?

     这不就是poj 2559 Largest Rectangle in a Histogram 这道题吗?这样我们的思路也就得出了,我们可以先对读入的数据预处理一下,统计每一列的连续和,然后对每一行维护一个单调栈,求出以每一行为底的最大矩阵的大小,最后取最大值。

      1 #include<stack>
      2 #include<cstdio>
      3 #include<string>
      4 #include<cstring>
      5 #include<queue>
      6 #include<cmath>
      7 #include<algorithm>
      8 #include<map>
      9 #include<iostream>
     10 #define maxn 1005
     11 using namespace std;
     12 
     13 stack<int>s;
     14 
     15 inline int read()
     16 {
     17     char c=getchar();
     18     int res=0,x=1;
     19     while(c<'0'||c>'9')
     20     {
     21         if(c=='-')
     22         x=-1;
     23         c=getchar();
     24     }
     25     while(c>='0'&&c<='9')
     26     {
     27         res=res*10+(c-'0');
     28         c=getchar();
     29     }
     30     return x*res;
     31 }
     32 
     33 long long ans;
     34 int n,m,a[maxn],w[maxn];
     35 int ju[maxn][maxn];
     36 char aa;
     37 
     38 int main()
     39 {
     40     n=read();m=read();
     41     for(int i=1;i<=n;i++)
     42     {
     43         for(int j=1;j<=m;j++)
     44         {
     45             scanf("%s",&aa);
     46             if(aa=='F')
     47             {
     48                 ju[i][j]=1;
     49             }
     50             if(aa=='R')
     51             {
     52                 ju[i][j]=0;
     53             }
     54         }
     55     }
     56     for(int j=1;j<=m;j++)
     57     {
     58         for(int i=1;i<=n;i++)
     59         {
     60              if(ju[i][j]==1)
     61              {
     62                  ju[i][j]=ju[i-1][j]+1;
     63             }
     64             else
     65             {
     66                 ju[i][j]=0;
     67             }
     68         }
     69     }
     70     for(int i=1;i<=n;i++)
     71     {
     72         for(int j=1;j<=m;j++)
     73         {
     74             a[j]=ju[i][j];
     75         }
     76         a[1+m]=0;
     77         while(s.size()) s.pop();
     78         for(int j=1;j<=m+1;j++)
     79         {
     80             if(s.empty()||a[j]>=s.top())
     81             {
     82                 s.push(a[j]);
     83                 w[s.size()]=1;
     84             }
     85             else
     86             {
     87                 int mi=0;
     88                 while(!s.empty()&&a[j]<s.top())
     89                 {
     90                     mi+=w[s.size()];
     91                     ans=max(ans,(long long)mi*s.top());
     92                     s.pop();
     93                 }
     94                 s.push(a[j]);
     95                 w[s.size()]=mi+1;
     96             }
     97         }
     98     }
     99     printf("%lld
    ",ans*3);
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/snowy2002/p/10288279.html
Copyright © 2011-2022 走看看