题目:统计一个字母矩阵中最大的相同字母的面积,有些字母可以换成其他字母。
分析:dp,单调队列。计算分三种分别换成a,b,c求出最大的子矩阵,求出最大即可。
然后就是单调队列优化的查询算法了,确定每个点右(左)边第一个比他小的点;
T(N)=O(N^2)。
说明:(2011-09-19 08:15)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char maps[ 1005 ][ 1005 ];
int smap[ 1005 ][ 1005 ];
int S[ 1005 ];
int L[ 1005 ];
int R[ 1005 ];
int SMQ[ 1005 ];
int calc( char c, int k )
{
switch( k ) {
case 1: if ( c == 'a' || c == 'w' || c == 'y' || c == 'z' )
return 1;else return 0;
case 2: if ( c == 'b' || c == 'w' || c == 'x' || c == 'z' )
return 1;else return 0;
case 3: if ( c == 'a' || c == 'x' || c == 'y' || c == 'z' )
return 1;else return 0;
}
return 0;
}
int main()
{
int n,m;
while ( ~scanf("%d%d",&n,&m) ) {
for ( int i = 1 ; i <= n ; ++ i )
scanf("%s",&maps[ i ][ 1 ]);
int Max = 0;
for ( int k = 1 ; k <= 3 ; ++ k ) {
for ( int i = 1 ; i <= n ; ++ i )
for ( int j = 1 ; j <= m ; ++ j )
smap[ i ][ j ] = calc( maps[ i ][ j ], k );
memset( S, 0, sizeof( S ) );
for ( int i = 1 ; i <= n ; ++ i ) {
for ( int j = 1 ; j <= m ; ++ j )
if ( smap[ i ][ j ] ) ++ S[ j ];
else S[ j ] = 0;
S[ 0 ] = S[ m+1 ] = -1;
SMQ[ 0 ] = 0;
int tail1 = 0;
for ( int i = 1 ; i <= m+1 ; ++ i ) {
while ( S[ SMQ[ tail1 ] ] > S[ i ] )
R[ SMQ[ tail1 -- ] ] = i;
SMQ[ ++ tail1 ] = i;
}
SMQ[ 0 ] = m+1;
int tail2 = 0;
for ( int i = m ; i >= 0 ; -- i ) {
while ( S[ SMQ[ tail2 ] ] > S[ i ] )
L[ SMQ[ tail2 -- ] ] = i;
SMQ[ ++ tail2 ] = i;
}
for ( int i = 1 ; i <= m ; ++ i )
if ( Max < S[ i ]*(R[ i ]-L[ i ]-1) )
Max = S[ i ]*(R[ i ]-L[ i ]-1);
}
}
printf("%d\n",Max);
}
return 0;
}