LA 3029
求最大子矩阵问题,主要考虑枚举方法,直接枚举肯定是不行的,因为一个大矩阵的子矩阵个数是指数级的,因此应该考虑先进行枚举前的扫描工作。
使用left,right,up数组分别记录从i,j位置可以向左,右,上扩展的最大距离,那么最终只需要枚举每一个方块即可使用(right-left)*up
#include <iostream> #include <cstdio> #include <cstring> #define M(a) memset(a,0,sizeof(a)) const int maxn=1e3+10; char a[maxn][maxn]; int up[maxn][maxn],right[maxn][maxn],left[maxn][maxn]; int m,n; int max(int x1,int x2) { return x1>x2?x1:x2; } int min(int x1,int x2) { return x1>x2?x2:x1; } void Init() { scanf("%d%d",&m,&n); for(int i=1; i<=m; i++) for(int j=1; j<=n; j++) std::cin>>a[i][j]; M(up); M(right); M(left); for(int i=1; i<=m; i++) { int lo=0; for(int j=1; j<=n; j++) { if(a[i][j]==‘R‘) { up[i][j]=0; left[i][j]=0; lo=j; } else { if(i==1) { up[i][j]=1; left[i][j]=lo+1; } else { up[i][j]=up[i-1][j]+1; left[i][j]=max(lo+1,left[i-1][j]); } } } int ro=n+1; for(int j=n; j>=1; j--) { if(a[i][j]==‘R‘) { right[i][j]=n+1; ro=j; } else { if(i==1) { right[i][j]=ro-1; } else { right[i][j]=min(ro-1,right[i-1][j]); } } } } } void Work() { int ans=-1e9; for(int i=1; i<=m; i++) for(int j=1; j<=n; j++) { ans=max(ans,(right[i][j]-left[i][j]+1)*up[i][j]); } printf("%d\n",3*ans); } int main() { int T; scanf("%d",&T); while(T--) { Init(); Work(); } return 0; }
原文:http://www.cnblogs.com/zsyacm666666/p/4918445.html