1. 程式人生 > >poj1964最大子矩陣 (單調棧加列舉)

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);
	}
	
}