最大子矩阵,(City Game)SEERC 2004,LA 3029
白书上的例题,看了两节课,终于理解了。DP的思想。
扫描的时候维护 up朝上能有多少空格,left 最多朝左走到多少,right 朝右走到多少。
所以只需要扫描一遍即可得出答案 = up*(right-left+1)
我定义left数组的时候跟 iostream 冲突了。
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<stack> //#include<iostream> #include<list> #include<set> #include<cmath> #define INF 0x7fffffff #define eps 1e-8 #define LL long long #define PI 3.141592654 #define CLR(a,b) memset(a,b,of(a)) #define FORi(n) for(int i=0;i<n;i++) #define FORj(n) for(int j=0;j<n;j++) #define FORk(n) for(int k=0;k<n;k++) #define debug puts("==fuck==") #define acfun std::ios::sync_with_stdio(false) #define SIZE 1000+10 using namespace std; bool g[SIZE][SIZE]; int up[SIZE][SIZE]; int left[SIZE][SIZE]; int right[SIZE][SIZE]; int main() { int n,m; int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); FORi(n) FORj(m) { char ch; scanf("%c",&ch); while(ch!='R'&&ch!='F') scanf("%c",&ch); if(ch=='R')g[i][j]=1; else g[i][j]=0; } int ans=0; FORi(n) { int lo=-1,ro=m; FORj(m) { if(g[i][j]) up[i][j]=left[i][j]=0,lo=j; else { if(i==0) { up[i][j]=1; left[i][j]=lo+1; } else { up[i][j]=up[i-1][j]+1; left[i][j]=max(left[i-1][j],lo+1); } } } for(int j=m-1;j>=0;j--) { if(g[i][j]) right[i][j]=m,ro=j; else { if(i==0) right[i][j]=ro-1; else right[i][j]=min(right[i-1][j],ro-1); ans=max(ans,up[i][j]*(right[i][j]-left[i][j]+1)); } } } // FORi(n) // { // FORj(m) // printf("%3d ",up[i][j]*(right[i][j]-left[i][j]+1)); // printf("\n"); // } printf("%d\n",ans*3); } }
原文地址:http://blog.csdn.net/dongshimou/article/details/39314197