最大矩形土地 单调栈或者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
所以我们考虑构建一个新的矩阵
找最大的面积

posted @ 2019-09-20 17:09  ALEZ  阅读(187)  评论(0)    收藏  举报