P4147 玉蟾宫--单调栈
P4147 玉蟾宫
题目背景
有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
题目描述
这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。
现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。
但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。
输入输出格式
输入格式:
第一行两个整数N,M,表示矩形土地有N行M列。
接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。
输出格式:
输出一个整数,表示你能得到多少银子,即(3*最大'F'矩形土地面积)的值。
输入输出样例
这是一道非常经典的题目。看到学长们个个都用悬线法来做,无奈本蒟蒻水平过低,只会用单调栈来切这道题。
我们可以把F看做1,R看做0。
来看下面这个矩阵:
看起来这道题似乎无从下手,但是如果我们把每一列1的连续和求出来,像这样:
也许我们仍然没能发现什么规律,但是不要紧,我们接着看:
我们尝试以每一行作为这个矩形的底边,找出图中最大的矩形,也就是图中的染色部分,有没有想起点什么?
这不就是poj 2559 Largest Rectangle in a Histogram 这道题吗?这样我们的思路也就得出了,我们可以先对读入的数据预处理一下,统计每一列的连续和,然后对每一行维护一个单调栈,求出以每一行为底的最大矩阵的大小,最后取最大值。
1 #include<stack> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<queue> 6 #include<cmath> 7 #include<algorithm> 8 #include<map> 9 #include<iostream> 10 #define maxn 1005 11 using namespace std; 12 13 stack<int>s; 14 15 inline int read() 16 { 17 char c=getchar(); 18 int res=0,x=1; 19 while(c<'0'||c>'9') 20 { 21 if(c=='-') 22 x=-1; 23 c=getchar(); 24 } 25 while(c>='0'&&c<='9') 26 { 27 res=res*10+(c-'0'); 28 c=getchar(); 29 } 30 return x*res; 31 } 32 33 long long ans; 34 int n,m,a[maxn],w[maxn]; 35 int ju[maxn][maxn]; 36 char aa; 37 38 int main() 39 { 40 n=read();m=read(); 41 for(int i=1;i<=n;i++) 42 { 43 for(int j=1;j<=m;j++) 44 { 45 scanf("%s",&aa); 46 if(aa=='F') 47 { 48 ju[i][j]=1; 49 } 50 if(aa=='R') 51 { 52 ju[i][j]=0; 53 } 54 } 55 } 56 for(int j=1;j<=m;j++) 57 { 58 for(int i=1;i<=n;i++) 59 { 60 if(ju[i][j]==1) 61 { 62 ju[i][j]=ju[i-1][j]+1; 63 } 64 else 65 { 66 ju[i][j]=0; 67 } 68 } 69 } 70 for(int i=1;i<=n;i++) 71 { 72 for(int j=1;j<=m;j++) 73 { 74 a[j]=ju[i][j]; 75 } 76 a[1+m]=0; 77 while(s.size()) s.pop(); 78 for(int j=1;j<=m+1;j++) 79 { 80 if(s.empty()||a[j]>=s.top()) 81 { 82 s.push(a[j]); 83 w[s.size()]=1; 84 } 85 else 86 { 87 int mi=0; 88 while(!s.empty()&&a[j]<s.top()) 89 { 90 mi+=w[s.size()]; 91 ans=max(ans,(long long)mi*s.top()); 92 s.pop(); 93 } 94 s.push(a[j]); 95 w[s.size()]=mi+1; 96 } 97 } 98 } 99 printf("%lld\n",ans*3); 100 return 0; 101 }