输入样例:
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
我们对这个操作一下,变成0.1矩阵(单纯为了好看):
011111
111111
000111
111111
111111
然后,悬线法是什么呢?
悬线的定义,就是一条竖线,这条竖线要满足上端点在整个矩形上边界或者是一个障碍点。然后以这条悬线进行左右移动,直到移至障碍点或者是矩阵边界,进而确定这条悬线所在的极大矩阵。
所谓线,就是我们用up数组记录的从任意一个点能向上延伸的最大长度。
然后我们用l,r两个数组记录对于这个点能向左向右延伸的最大长度。
需要对它们进行预处理:
//处理l
for(i=1;i<=n;i++)
for(j=2;j<=m;j++)
if(map[i][j]==1&&map[i][j-1]==1)
l[i][j]=l[i][j-1];
//处理r
for(i=1;i<=n;i++)
for(j=m-1;j>0;j--)
if(map[i][j]==1&&map[i][j+1]==1)
r[i][j]=r[i][j+1];
然后我们要对每个点找它能生成的最大矩形面积。
举个栗子,我们现在只考虑一个点向右边延伸:
这个时候数组r就派上用场了,对于up=1,它能延伸至最右边(已被r(1,1)记录) 那么S=up*r(1,1);
然后,考虑(2,1),此时数组UP(2,1)可以向上延伸1,则up(2,1)=2;向右我们肯定是取min(r(2,1),r(1,1));那么就会求以下的面积:
同理 ,我们遍历到(3,1)时,就会得到:
代码:
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(i>1&&map[i][j]==1&&map[i-1][j]==1){
r[i][j]=min(r[i][j],r[i-1][j]);
l[i][j]=max(l[i][j],l[i-1][j]);
up[i][j]=up[i-1][j]+1;
}
ans=max(ans,(r[i][j]-l[i][j]+1)*up[i][j]);
}
}
以上是照搬牛客博主,加了些自己的理解。仅用作笔记,侵权删qwq。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int Read() {
int x = 0, f = 1;
char c = getchar();
while (c > '9' || c < '0') {
if (c == '-')f = -1;
c = getchar();
};
while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
return x * f;
}//读入优化
inline int Readc() {
char c = getchar();
while (c != 'R' && c != 'F')c = getchar();
if (c == 'F')return 1;
return 0;
}//F能用,E不能用
inline int max(int x, int y) {
return x > y ? x : y;
}
inline int min(int x, int y) {
return x < y ? x : y;
}
//max和min最好自己打
int n, m, ans1, ans, map[1001][1001];;
//ans:最大矩形;map[i][j]:(i,j)的值 ,0不能用,1可以用
int l[2018][2018], r[2018][2018];
//l[i][j],r[i][j],up[i][j]分别表示(i,j)左,右能到达的最远的点的纵坐标
int up[2018][2018];
//向上到达最远的点的距离
int main() {
register int i, j;
ans = 0;
n = Read(), m = Read();
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
map[i][j] = Readc(), up[i][j] = 1, r[i][j] = l[i][j] = j;
//处理l
for (i = 1; i <= n; i++)
for (j = 2; j <= m; j++)
if (map[i][j] == 1 && map[i][j - 1] == 1)
l[i][j] = l[i][j - 1];
//处理r
for (i = 1; i <= n; i++)
for (j = m - 1; j > 0; j--)
if (map[i][j] == 1 && map[i][j + 1] == 1)
r[i][j] = r[i][j + 1];
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (i > 1 && map[i][j] == 1 && map[i - 1][j] == 1) {
r[i][j] = min(r[i][j], r[i - 1][j]);
l[i][j] = max(l[i][j], l[i - 1][j]);
up[i][j] = up[i - 1][j] + 1;
}
if (map[i][j] == 0)continue;
ans = max(ans, (r[i][j] - l[i][j] + 1) * up[i][j]);
}
}
printf("%d", 3 * ans);
return 0;
}