Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 4730 | Accepted: 1876 |
Description
Each area has its width and length. The area is divided into a grid of equal square units.The rent paid for each unit on which you're building stands is 3$.
Your task is to help Bob solve this problem. The whole city is divided into K areas. Each one of the areas is rectangular and has a different grid size with its own length M and width N.The existing occupied units are marked with the symbol R. The unoccupied units are marked with the symbol F.
Input
R – reserved unit
F – free unit
In the end of each area description there is a separating line.
Output
Sample Input
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
Sample Output
450
本题从本质上说是dp。
从上到下依次枚举每一行,每加入如一行,枚举以该行某一点为端点,所能形成的最大的高,求出这些高左右能扫过的最大面积,则只要从上到下一直维护一个最大面积即可。
对每一个点能到达的最大高度,可用(当前行号) - (能达的最小的行号) + 1求得,因此先求每一个每一个点能到达的最小行号。每一个点的能到达最小行号能通过其正上方的相应值求得。设up[i][j]表示第i行j列能到达的最小行号,则
第一行能到达的就是自己;非空地不考虑
i > 1时若up[i-1][j],up[i][j]都为空地则up[i][j] = up[i-1][j],
若up[i-1][j]不为空则能到达的就是自己
对于每一个点,求最左能到达的最大列号left,做右能到达的行号right
第一列能向左到达的就是自己;非空地不考虑
i > 1时若left[i-1][j],left[i][j]都为空地则lefti][j] = left[i-1][j],
若left[i-1][j]不为空则能到达的就是自己
对right同left
则高能扫过的左右宽度 [i][j] = left[i][j] - right[i][j] +1;
left[i][j] = max(left[i - 1][j],left[i][j]) (当前行 > i >= up[i][j] )
right[i][j] = min(right[i - 1][j],right[i][j]) (当前行 > i >= up[i][j])
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int MAX = 1000 + 5;
struct sq
{
int up,left,right,empty;//empty = 1 代表 是空地, 0 代表有障碍
}mtx[MAX][MAX];
void caculate(int row,int col)
{
//计算能到达的最上的编号
for(int r = 1; r < row; r++)
for(int c = 0; c < col; c++)
if(mtx[r][c].empty && mtx[r - 1][c].empty)mtx[r][c].up = mtx[r - 1][c].up;//若上面为障碍 则向上能到达的最小是自己
for(int r = 0; r < row; r++)//计算向左右能到达的最 远的下标
{
for(int c = 1; c < col; c++)
if(mtx[r][c].empty && mtx[r][c - 1].empty)mtx[r][c].left = mtx[r][c - 1].left;
for(int c = col - 2; c >= 0; c--)
if(mtx[r][c].empty && mtx[r][c + 1].empty)mtx[r][c].right = mtx[r][c + 1].right;
}
int m = 0;
for(int r = 1; r < row; r++)
for(int c = 0; c < col; c++)
{
if(!mtx[r][c].empty || !mtx[r - 1][c].empty)continue;//若上面是障碍 向左右能到达的值就是 本行真能到达的最远 自己是障碍无需继续计算
mtx[r][c].left = max(mtx[r - 1][c].left, mtx[r][c].left);
mtx[r][c].right = min(mtx[r - 1][c].right, mtx[r][c].right);
}
for(int r = 0; r < row; r++)
for(int c = 0; c < col; c++)
{
if(!mtx[r][c].empty)continue;
// printf("ROW:%d COL:%d U:%d L:%d R:%d kuan:%d gao %d\n",r,c,mtx[r][c].up,mtx[r][c].left,mtx[r][c].right,mtx[r][c].right - mtx[r][c].left + 1,r - mtx[r][c].up + 1);
m = max(m, (r - mtx[r][c].up + 1) * (mtx[r][c].right - mtx[r][c].left + 1));
}
printf("%d\n",m * 3);
}
int main(int argc, char *argv[])
{
int t,m,n;
scanf("%d",&t);
while(t--)
{
scanf("%d%d\n",&m,&n);
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
int c;
while((c = getchar()) != 'F' && c != 'R')continue;
c = c == 'F' ? 1 : 0;
sq s;
s.up = i;
s.left = j;
s.right = j;
s.empty = c;
mtx[i][j] = s;// (sq){i, j, j, c};
}
}
caculate(m, n);
}
//system("PAUSE");
return EXIT_SUCCESS;
}
/*
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
*/