http://acm.hdu.edu.cn/showproblem.php?pid=2870
题目意思是给一个字符矩阵“w”可以替换成“a”或者“b”,“w”可以替换成“a”或者“b”,“x”可以替换成“b”或者“c”,“z”可以替换成“a”或者“b”或者“c”。问可以找出一个字符一样的最大的子矩阵是多大。
思路是列出三种情况,就是全部替换成a的时候取得的子矩阵是全有a组成的,同理b,c。现在的问题就是求最大子矩阵的问题了。三个数组(A,B,C)分别表示三种状态,我用0表示不是我求的最大矩阵字符的字符,1反之。现在这一问题是否为也就是http://acm.hdu.edu.cn/showproblem.php?pid=1506这个问题了,每一行这么求一次就好了。其实问题的关键就转换成求一个数字左右两边大于等于这个数字的个数,分别用两个数组来存(Alnumber,Arnumber,Blnumber,Brnumber,Clnumber,Crnumber,)。
附上很丑的代码,跑了656ms
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <memory.h>
#define maxn 1005
using namespace std;
char map;
int A[maxn][maxn],B[maxn][maxn],C[maxn][maxn];
int Alnumber[maxn],Arnumber[maxn],Blnumber[maxn],Brnumber[maxn],Clnumber[maxn],Crnumber[maxn];
int main()
{
//freopen("in.txt","r",stdin);
int col,row,i,j;
while(scanf("%d%d",&col,&row)!=EOF&&col&&row)
{
getchar();
memset(A,0,sizeof A);
memset(B,0,sizeof B);
memset(C,0,sizeof C);
for(i = 1 ;i<=col ; i++)
{
for(j= 1;j<=row;j++)
{
scanf("%c",&map);
if(map=='a'||map=='w'||map=='y'||map=='z')
A[i][j] =A[i-1][j] +1;
else A[i] [j] =0;
if(map=='b'||map=='w'||map=='x'||map=='z')
B[i][j] =B[i-1][j] +1;
else B[i] [j] =0;
if(map=='c'||map=='x'||map=='y'||map=='z')
C[i][j] =C[i-1][j] +1;
else C[i] [j] =0;
}
getchar();
}
int ans=0;
for(i = 1;i<=col ;i++)
{
memset(Alnumber,0,sizeof Alnumber);
memset(Blnumber,0,sizeof Blnumber);
memset(Clnumber,0,sizeof Clnumber);
memset(Arnumber,0,sizeof Arnumber);
memset(Brnumber,0,sizeof Brnumber);
memset(Crnumber,0,sizeof Crnumber);
Alnumber[1]=1,Arnumber[row]=row;
Blnumber[1]=1,Brnumber[row]=row;
Clnumber[1]=1,Crnumber[row]=row;
for(j = 2 ; j <= row ; j++)
{
int tt=j,kk=j,cc=j;
while(tt>1&&A[i][j]<=A[i][tt-1])tt=Alnumber[tt-1];
Alnumber[j]=tt;
while(kk>1&&B[i][j]<=B[i][kk-1])kk=Blnumber[kk-1];
Blnumber[j]=kk;
while(cc>1&&C[i][j]<=C[i][cc-1])cc=Clnumber[cc-1];
Clnumber[j]=cc;
}
for(j = row-1 ; j >= 1 ; j--)
{
int tt=j,kk=j,cc=j;
while(tt<row&&A[i][j]<=A[i][tt+1])tt=Arnumber[tt+1];
Arnumber[j]=tt;
while(kk<row&&B[i][j]<=B[i][kk+1])kk=Brnumber[kk+1];
Brnumber[j]=kk;
while(cc<row&&C[i][j]<=C[i][cc+1])cc=Crnumber[cc+1];
Crnumber[j]=cc;
}
for(j = 1 ; j <= row ; j++)
{
ans=max(ans,A[i][j]*(1-Alnumber[j]+Arnumber[j]));
ans=max(ans,B[i][j]*(1-Blnumber[j]+Brnumber[j]));
ans=max(ans,C[i][j]*(1-Clnumber[j]+Crnumber[j]));
}
}
printf("%d\n",ans);
}
return 0;
}