poj1964最大子矩阵 (单调栈加枚举)

题目传送门

题目大意:

一个矩阵中,求F组成的矩阵的面积,(答案乘以三)。

思路:n如果是小于100的,就可以通过前缀和,然后三重循环暴力找,和poj1050很像,但由于是1000,就不可以了,时间复杂度太高。

这道题的类别是单调栈,仔细想一下,发现其实就是先统计每一行网上有多少个长方形,然后再枚举每一行,算出最大的maxx,相当于poj2559的加强版。代码有很多细节要注意,最大的坑是,输入的图,两个符号之间不一定只有一个空格,所以每一个字符都要用%s输入,对拍拍了好久都不知道错哪里,看了题解才发现,(最难受的是看的最多的人的题解还是错的)辣鸡题目,浪费我时间。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<math.h>
#include<cmath>
#include<time.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<algorithm>
#include<numeric>
#include<stack>
using namespace std;
const int maxn=1010;
char mp[maxn][maxn];
int n,m,u[maxn][maxn];
struct dian{
	int r,h;
};

int main(){
	int t;
	cin>>t;
	stack<dian>s;
	while(t--){
		
		memset(u,0,sizeof(u));
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				scanf("%s",mp[i]);
				if(mp[i][0]=='F'){
					u[i][j]=u[i-1][j]+1;
				}else{
					u[i][j]=0;
				}
			}
		}
		int maxx=0;
		int r;
		for(int i=1;i<=n;i++){
			while(!s.empty())s.pop();
			for(int j=1;j<=m+1;j++){
				dian a,b;
				r=0;
				if(s.empty()){
					a.h=u[i][j];
					a.r=1;
					s.push(a);
					continue;
			}
			a=s.top();
			if(u[i][j]>=a.h){
				b.h=u[i][j];
					b.r=1;
					s.push(b);
			}
				else{
					r=0;
					while(a.h>u[i][j]&&!s.empty()){
						a=s.top();
						r+=a.r;
						int h=a.h;
						s.pop();
						maxx=max(maxx,h*r);
						if(!s.empty())
						a=s.top();
					}
					a.r=r+1;
					a.h=u[i][j];
					s.push(a);
				}
			}
		}
		printf("%d\n",3*maxx);
	}
	
} 

posted @ 2018-06-07 15:06  光芒万丈小太阳  阅读(470)  评论(0编辑  收藏  举报