LA 3029 City Game
LA 3029
求最大子矩阵问题,主要考虑枚举方法,直接枚举肯定是不行的,因为一个大矩阵的子矩阵个数是指数级的,因此应该考虑先进行枚举前的扫描工作。
使用left,right,up数组分别记录从i,j位置可以向左,右,上扩展的最大距离,那么最终只需要枚举每一个方块即可使用(right-left)*up
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstring> #define M(a) memset(a,0,sizeof(a)) using namespace std; const int maxn=1e3+10; char mat[maxn][maxn]; int up[maxn][maxn],lef[maxn][maxn],righ[maxn][maxn]; int m,n; void Init() { cin>>m>>n; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) cin>>mat[i][j]; } M(up); M(lef); M(righ); } void Work() { for(int i=1;i<=m;i++) { int l=0; for(int j=1;j<=n;j++) { up[i][j]=up[i-1][j]+1; if(mat[i][j]=='R') { up[i][j]=0; lef[i][j]=0;//这里设它为零,避免对后面的取值产生影响 l=j; //同时也无需担心会对ans取值产生影响,因为up(i,j)为零 } else { if(i==1) lef[i][j]=l+1; else lef[i][j]=max(lef[i-1][j],l+1); } } int r=n+1; for(int j=n;j>=1;j--) { if(mat[i][j]=='R') { r=j; righ[i][j]=n+1; } else { if(i==1) righ[i][j]=r-1; else righ[i][j]=min(righ[i-1][j],r-1); } } } } void Print() { int ans=0; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) { ans=max(ans,3*(righ[i][j]-lef[i][j]+1)*up[i][j]); } cout<<ans<<endl; } int main() { int T; cin>>T; while(T--) { Init(); Work(); Print(); } return 0; }