最大矩形土地 单调栈或者DP

问题:
有一天,小猫\(rainbow\)\(freda\)来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
这片土地被分成\(N \times M\) 个格子,每个格子里写着\(’R’\)或者\(’F’\)\(R\)代表这块土地被赐予了\(rainbow\)\(F\)代表这块土地被赐予了\(freda\)
现在\(freda\)要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着\(’F’\)并且面积最大。
它们决定,如果你找到的土地面积为\(S\),它们给你\(3 \times S\)两银子。

解:
这题有多种做法 双端队列的解法我就不说了

这里介绍单调栈和DP 的方法

1.单调栈
首先我们先注意到对于一个合法的序列 答案一定是长度 $\times min(H) $
并且对于一个单调的栈 从左到右每个元素都能够和右边的配成对 并且高度为当前元素的H
考虑当栈顶元素的H>枚举到的H
那么就不满足单调性 所以我们需要进行强制单调 好让成为一个单调的序列
最后考虑再次统计答案即可
code:

#include<bits/stdc++.h>
using namespace std;
int mapp[2000][2000];
int n,m;
int ans=0;
int sum[2000][2000];
struct node
{
    int H,l;
};
stack<node> S;
void get()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int len=0;
            while(S.size()&&S.top().H>sum[i][j])
            {
                 len+=S.top().l;
                 ans=max(ans,len*S.top().H);
                 S.pop();
            }
            S.push(node{sum[i][j],len+1});
        }
        
        int len=0;
        while(S.size())
        {
            len+=S.top().l;
            ans=max(ans,len*S.top().H);
            S.pop();
        }
    }
}
void ssum()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            sum[i][j]=(mapp[i][j]?sum[i-1][j]+1:0);
        }
    }
}
int main()
{
    char c;

    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
        {
            c=getchar();
            while(c!='F'&&c!='R')
            {
                c=getchar();
            }
            if(c=='F')
            {
                mapp[i][j]=1;
            }
            else
            mapp[i][j]=0;
        }
    }
    ssum();
    get();
    cout<<3*ans;
    
}

2 DP
对于每个点考虑
当前这个点向左所能延伸到到最远的距离就是 他上面和他的离得最近的距离
dp一下即可


来道经典题:
翻转矩阵
何老板给你一个H*W的网格棋盘,每个方格都被涂上了黑色或白色。
你可以进行任意次下列操作:
  任选一行(或一列),将该行(列)的方格颜色翻转,即白色变黑,黑色变白。
何老板希望你能在棋盘上找出最大的一个黑色矩形。该矩形中的方格全是黑色,请你输出该矩形的面积。

注意到能够成为矩形到充要条件是每个2$\times$2 的小矩形异或值为0
所以我们考虑构建一个新的矩阵
找最大的面积

转载于:https://www.cnblogs.com/OIEREDSION/p/11558341.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值