本题就是要求最大子矩阵--
思路: 1.针对于dp数组中代表的每一个点,我们为其设置它的高度h。
当这个点是障碍时,我们把它的高度设置为0,否则它的高度是垂直方向的上一个点加1。
2.我们设法求出该点向左和向右能够延伸的最大距离。然后用right - left + 1就等于边的长度。
3.我们用高乘以边得到面积,通过判断后找到最大的面积,就可以得到答案了。
如何表示高度: 在输入的时候就行判断,然后对dp数组进行初始化。如果是F,则h[i][j] = h[i-1][j] + 1,否则h[i][j] = 0。
如何表示宽度: 我们按行进行遍历,对于第i行的点,分别为它们设置下标对应的l,r数组进行表示left,right。
以找左边最大延伸距离为例:当向左边延伸的时候,我们判断该点的左边的点的高度,如果左边点 的高度大于等于该点的高度,说明这个点是可以延伸到的,所以我们继续向该点的下一个点进行延 伸。
for(int j = 1; j <= N; j++){
while(h[i][l[j]-1] >= h[i][j]){
l[j] = l[l[j]-1];
}
}
借用的代码:
#include<stdio.h> #include<string.h> /* 2 5 6 R F F F F F F F F F F F R R R F F F F F F F F F F F F F F F 5 5 R R R R R R R R R R R R R R R R R R R R R R R R R */ int h[1100][1100],l[1100],r[1100]; int main() { int K,M,N; char ch[4]; scanf("%d",&K); while(K--) { memset(h,0,sizeof(h)); memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); scanf("%d%d",&M,&N); for(int i = 1; i <= M; i++) { for(int j = 1; j <= N; j++) { scanf("%s",ch); if(ch[0] == 'F') h[i][j] = h[i-1][j] + 1; else h[i][j] = 0; } } __int64 MaxArea = -0xffffff0; for(int i = 1; i <= M; i++) { for(int j = 1; j <= N; j++) l[j] = r[j] = j; l[0] = 1; r[N+1] = N; h[i][0] = -1; h[i][N+1] = -1; for(int j = 1; j <= N; j++) { //如果收它左边的点的高度大于等于它,就将它们对于的左值赋值为左边那个点,这样可以保证合适的最左点 while(h[i][l[j]-1] >= h[i][j]){ l[j] = l[l[j]-1]; } } //寻找最右点 for(int j = N; j >= 1; j--) { while(h[i][r[j]+1] >= h[i][j]) r[j] = r[r[j]+1]; } for(int j = 1; j <= N; j++) { if(h[i][j]*(r[j]-l[j]+1) > MaxArea) MaxArea = h[i][j]*(r[j]-l[j]+1); } } printf("%I64d\n",MaxArea*3); } return 0; }