zoukankan      html  css  js  c++  java
  • BZOJ 3039 玉蟾宫

    Description

    有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
    这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。
    现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。
    但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。


    Input

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

    Output

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

    Sample Input

    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

    Sample Output

    45

    HINT



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

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

    题意:给你一个0 1的矩阵,求最大的全是1的矩阵。

    题解:枚举矩形下方的两个点(这个过程只需要枚举3个坐标),然后再找最大能够向上延伸多高。容易预处理出每个位置向上最多延伸多高,那么要求的就是这两个点直接所有点(包括这两个点)的延伸高度的最小值。

       对于区间最小值作贡献问题,一个常用的套路是枚举最小值,考虑贡献。那么可以使用单调栈(查询向左和向右第一个小于它的高度的值,向左向右维护一个单调递增的栈即可)处理出一个数左边第一个小于它的位置和右边第一个小于它的位置。这两个位置之间的都大于它,此时这个数作为最小值,最大宽度为位置差,直接计算贡献即可。O(n*m)
     
    暴力(n^3) 不能过的
    #include <bits/stdc++.h>
    
    const int maxn=1005;
    int n, m, a[maxn][maxn];
    
    int main()
    {
        char s[10];
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                scanf("%s", s);
                a[i][j]= s[0]=='F'? 1+a[i][j-1]:a[i][j-1];
            }
        int ans=0;
        for(int l=1; l<=m; l++)
            for(int r=l; r<=m; r++)
            {
                int tans=0;
                for(int i=1; i<=n; i++)
                {
                    if(a[i][r]-a[i][l-1]==r-l+1) tans+=a[i][r]-a[i][l-1];
                    else tans=0;
                    ans=std::max(ans, tans);
                }
            }
        printf("%d
    ", ans*3);
        return 0;
    }
    View Code
    单调栈:
    /**************************************************************
        Problem: 3039
        User: strangers
        Language: C++
        Result: Accepted
        Time:780 ms
        Memory:5244 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
     
    const int maxn=1005;
    int n, m, a[maxn][maxn];
    int ls[maxn], rs[maxn], stk[maxn], top;
     
    void debug()
    {
        for(int i=1; i<=m; i++)
            printf("ls[%d]=%d, rs[%d]=%d ", i, ls[i], i, rs[i]);
        printf("
    ");
    }
     
    int main()
    {
        char s[10];
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                scanf("%s", s);
                a[i][j]= s[0]=='F'? 1+a[i-1][j]:0;
            }
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            top=0, stk[top]=0;
            for(int j=1; j<=m; j++)
            {
                while(top && a[i][stk[top]]>=a[i][j]) top--;
                ls[j]=stk[top], stk[++top]=j;
            }
            top=0, stk[top]=m+1;
            for(int j=m; j; j--)
            {
                while(top && a[i][stk[top]]>=a[i][j]) top--;
                rs[j]=stk[top], stk[++top]=j;
            }
            //debug();
            for(int j=1; j<=m; j++)
                ans=std::max(ans, a[i][j]*(rs[j]-ls[j]-1));
        }
        printf("%d
    ", ans*3);
        return 0;
    }
    View Code
  • 相关阅读:
    c++ isdigit函数
    c++ swap函数
    1.2Hello, World!的大小
    1.2整型与布尔型的转换
    1.2打印ASCII码
    leetcode[170]Two Sum III
    leetcode[167]Two Sum II
    leetcode[1]Two Sum
    leetcode[2]Add Two Numbers
    leetcode[3]Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/Yokel062/p/11508608.html
Copyright © 2011-2022 走看看