BZOJ 3039: 玉蟾宫( 悬线法 )
最大子矩阵...悬线法..时间复杂度O(nm)
悬线法就是记录一个H向上延伸的最大长度(悬线), L, R向左向右延伸的最大长度, 然后通过递推来得到.
------------------------------------------------------------------
#include<bits/stdc++.h>
using namespace std;
#define ok(c) ((c) == 'F' || (c) == 'R')
const int maxn = 1009;
int H[maxn][maxn], L[maxn][maxn], R[maxn][maxn], N, M;
bool F[maxn][maxn];
void Read() {
cin >> N >> M;
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++) {
char c = getchar();
for(; !ok(c); c = getchar());
F[i][j] = c == 'F';
}
}
int main() {
Read();
for(int i = 0; i < N; i++) {
L[i][0] = F[i][0];
for(int j = 1; j < M; j++)
L[i][j] = F[i][j] ? L[i][j - 1] + 1 : 0;
R[i][M - 1] = F[i][M - 1];
for(int j = M - 2; ~j; j--)
R[i][j] = F[i][j] ? R[i][j + 1] + 1 : 0;
}
memset(H, 0, sizeof H);
for(int i = 1; i < N; i++)
for(int j = 0; j < M; j++) if(F[i][j] && F[i - 1][j]) {
H[i][j] = H[i - 1][j] + 1;
L[i][j] = min(L[i][j], L[i - 1][j]);
R[i][j] = min(R[i][j], R[i - 1][j]);
}
int ans = 0;
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++) if(F[i][j])
ans = max(ans, (H[i][j] + 1) * (L[i][j] + R[i][j] - 1));
cout << 3 * ans << "\n";
return 0;
}
------------------------------------------------------------------
3039: 玉蟾宫
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 581 Solved: 352
[Submit][Status][Discuss]
Description
有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。
现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。
但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。
Input
第一行两个整数N,M,表示矩形土地有N行M列。
接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。
Output
输出一个整数,表示你能得到多少银子,即(3*最大'F'矩形土地面积)的值。
Sample Input
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
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
Sample Output
45
HINT
对于50%的数据,1<=N,M<=200
对于100%的数据,1<=N,M<=1000
Source