/*
zju1985升级版 ^_^ 继上次那道题想了一天,本来想用O(N^2)的最大正方形求解,
想错了今天仔细一看,其实这道题目就是二维的最大矩形。
分析:我们将问题分解成最大矩形,即求解以k行为底边的图形中的最大矩形,
然后将问题合并,求出最大的矩形。
预处理: 求出以每行为底边的每一列从底边开始向上的最大高度MaxH。 O(N^2)
DP; 对于每一层底边,我们利用单调队列求解出本行的最大矩形。 O(N)
关于单调队列的求解分析,可参照zju1985的题解
总体时间:T(N) = O(N^2)+O(N)*O(N) = O(N^2)
*/
View Code
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 char Maps[ 1003 ][ 1003 ];
6 int MaxH[ 1003 ][ 1003 ];
7 int L[ 1003 ],R[ 1003 ];
8 int MUQ[ 1003 ];
9
10 int main()
11 {
12 int t,m,n;
13 while ( scanf("%d",&t) != EOF )
14 while ( t -- ) {
15 scanf("%d%d",&m,&n);getchar();
16 for ( int i = 1 ; i <= m ; ++ i )
17 for ( int j = 1 ; j <= n ; ++ j ) {
18 scanf("%c",&Maps[ i ][ j ]);
19 getchar();
20 }
21
22 //计算每条底边上的每列高度
23 memset( MaxH, 0, sizeof( MaxH ) );
24 for ( int i = 1 ; i <= m ; ++ i )
25 for ( int j = 1 ; j <= n ; ++ j )
26 if ( Maps[ i ][ j ] == 'F' )
27 MaxH[ i ][ j ] = MaxH[ i-1 ][ j ]+1;
28 else
29 MaxH[ i ][ j ] = 0;
30
31 for ( int i = 1 ; i <= m ; ++ i )
32 MaxH[ i ][ 0 ] = MaxH[ i ][ n+1 ] = -1;
33
34 int MaxV = 0;
35 for ( int i = 1 ; i <= m ; ++ i ) {
36 //计算每个点的左边界
37 int tail = 0;
38 MUQ[ 0 ] = 0;
39 for ( int j = 1 ; j <= n+1 ; ++ j ) {
40 while ( tail >= 0 && MaxH[ i ][ MUQ[ tail ] ] > MaxH[ i ][ j ] )
41 R[ MUQ[ tail -- ] ] = j;
42 MUQ[ ++ tail ] = j;
43 }
44 //计算每个点的右边界
45 tail = 0;
46 MUQ[ 0 ] = n+1;
47 for ( int j = n ; j >= 0 ; -- j ) {
48 while ( tail >= 0 && MaxH[ i ][ MUQ[ tail ] ] > MaxH[ i ][ j ] )
49 L[ MUQ[ tail -- ] ] = j;
50 MUQ[ ++ tail ] = j;
51 }
52 //求解
53 for ( int j = 1 ; j <= n ; ++ j ) {
54 int Temp = MaxH[ i ][ j ]*(R[ j ]-L[ j ]-1);
55 if ( MaxV < Temp )
56 MaxV = Temp;
57 }
58 }
59
60 printf("%d\n",MaxV*3);
61 }
62 return 0;
63 }