zoukankan      html  css  js  c++  java
  • [Nescafé 20] 玉蟾宫

    ★   输入文件:jademoon.in   输出文件:jademoon.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【背景】

    有一天,小猫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'矩形土地面积)的值。

    【样例输入】

    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
    

    【样例输出】

    45

    【提示】

    各个测试点1s

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

    【来源】

    http://www.tyvj.cn/Problem_Show.aspx?id=1939

    思路

    表解在这,我就不说话了;

    官方题解:

    们先来考虑这样一个问题,水平线上有一些宽度为1,高度不定的阴影区域,要求找到包含在这个区域内的一个矩形,使得矩形面积最大。

    如图所示,高度不一的柱形条就是阴影区域,不同颜色框出的矩形都满足要求,其中红色矩形的面积最大。

     

    维护一个栈中元素高度单调递增的栈,初始化栈中第一个元素高度宽度均为0。

    然后每次读入一个矩形,若它比栈顶元素还高就直接进栈;

    否则不断将栈中元素弹栈,直到当前栈顶元素能够与读入的矩形满足高度递增。

    弹栈过程中累加弹出的元素的宽度,然后每弹出一个就判断(当前弹出元素的高度×累加的宽度)能否更新最大面积ans。

    然后以新的矩形高度作高,刚才弹出栈的元素总宽度加上新矩形宽度作宽,把这个矩形插入到栈里。

    最终栈肯定是一个单调的,只需要再把栈一个个弹空,弹栈过程中仍像上面那样计算即可。

    这个算法的时间复杂度是O(n)的。

    在本题中,我们只需要枚举每一行以上的'F'作为阴影区域,用上述单调栈算法求一遍最大矩形面积即可。时间复杂度O(NM)。

    代码实现

     1 #include<cstdio>
     2 const int maxn=1e3+10;
     3 inline int max_(int x,int y){return x>y?x:y;}
     4 int n,m,ans;
     5 int map[maxn][maxn];
     6 char ch[3];
     7 int q[maxn],s[maxn],top;
     8 void do_stack(int k){
     9     q[top=1]=map[k][1],s[top]=1;
    10     for(int i=2;i<=m+1;i++){
    11         int j=0;
    12         while(map[k][i]<q[top]){
    13             j+=s[top];
    14             ans=max_(ans,q[top--]*j);
    15         }
    16         q[++top]=map[k][i],s[top]=j+1;
    17     }
    18 }
    19 int main(){
    20     freopen("jademoon.in","r",stdin);
    21     freopen("jademoon.out","w",stdout);
    22     scanf("%d%d",&n,&m);
    23     for(int i=1;i<=n;i++)
    24     for(int j=1;j<=m;j++){
    25         scanf("%s",ch);
    26         if(ch[0]=='F') map[i][j]=map[i-1][j]+1; 
    27     }
    28     for(int i=1;i<=n;i++){
    29         do_stack(i);
    30     }
    31     printf("%d
    ",ans*3);
    32     return 0;
    33 }
  • 相关阅读:
    使用CustomValidate自定义验证控件
    C#中金额的大小写转换
    Andriod出错之Unable to build: the file dx.jar was not loaded from the SDK folder!
    VC 编写的打字练习
    机房工作笔记Ping只有单向通
    web服务协同学习笔记(1)
    Dll 学习3 将MDI子窗口封装在DLL中
    机房工作学习文件共享
    Andriod出错之Failed to find an AVD compatible with target 'Android 2.2'
    Andriod出错之wrapper was not properly loaded first
  • 原文地址:https://www.cnblogs.com/J-william/p/7419800.html
Copyright © 2011-2022 走看看