[Nescafé 20] 玉蟾宫
★ 输入文件:jademoon.in
输出文件:jademoon.out
简单对比
时间限制:1 s
内存限制:128 MB
【背景】
有一天,小猫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'矩形土地面积)的值。
【样例输入】
5 6 R F F F F F F F F F F F R R R F F F F F F F F F F F F F F F
【样例输出】
45
【提示】
各个测试点1s
对于50%的数据,1<=N,M<=200
对于100%的数据,1<=N,M<=1000
【来源】
http://www.tyvj.cn/Problem_Show.aspx?id=1939
思路
表解在这,我就不说话了;
官方题解:
们先来考虑这样一个问题,水平线上有一些宽度为1,高度不定的阴影区域,要求找到包含在这个区域内的一个矩形,使得矩形面积最大。
如图所示,高度不一的柱形条就是阴影区域,不同颜色框出的矩形都满足要求,其中红色矩形的面积最大。
维护一个栈中元素高度单调递增的栈,初始化栈中第一个元素高度宽度均为0。
然后每次读入一个矩形,若它比栈顶元素还高就直接进栈;
否则不断将栈中元素弹栈,直到当前栈顶元素能够与读入的矩形满足高度递增。
弹栈过程中累加弹出的元素的宽度,然后每弹出一个就判断(当前弹出元素的高度×累加的宽度)能否更新最大面积ans。
然后以新的矩形高度作高,刚才弹出栈的元素总宽度加上新矩形宽度作宽,把这个矩形插入到栈里。
最终栈肯定是一个单调的,只需要再把栈一个个弹空,弹栈过程中仍像上面那样计算即可。
这个算法的时间复杂度是O(n)的。
在本题中,我们只需要枚举每一行以上的'F'作为阴影区域,用上述单调栈算法求一遍最大矩形面积即可。时间复杂度O(NM)。
代码实现
1 #include<cstdio> 2 const int maxn=1e3+10; 3 inline int max_(int x,int y){return x>y?x:y;} 4 int n,m,ans; 5 int map[maxn][maxn]; 6 char ch[3]; 7 int q[maxn],s[maxn],top; 8 void do_stack(int k){ 9 q[top=1]=map[k][1],s[top]=1; 10 for(int i=2;i<=m+1;i++){ 11 int j=0; 12 while(map[k][i]<q[top]){ 13 j+=s[top]; 14 ans=max_(ans,q[top--]*j); 15 } 16 q[++top]=map[k][i],s[top]=j+1; 17 } 18 } 19 int main(){ 20 freopen("jademoon.in","r",stdin); 21 freopen("jademoon.out","w",stdout); 22 scanf("%d%d",&n,&m); 23 for(int i=1;i<=n;i++) 24 for(int j=1;j<=m;j++){ 25 scanf("%s",ch); 26 if(ch[0]=='F') map[i][j]=map[i-1][j]+1; 27 } 28 for(int i=1;i<=n;i++){ 29 do_stack(i); 30 } 31 printf("%d\n",ans*3); 32 return 0; 33 }