LA 3029 City Game 最大子矩阵

一个n x m的矩阵中有很多障碍物.

现求一个最大的且不包含障碍物的子矩阵.

把每个格子向上延伸到障碍或者边界的连续的空格看做一条线段, 则对于该格来说, 它对应的一个子矩阵子矩阵即为这条线段左右可移动到的边界.

又知任何一个矩阵均可以由它最下层的某个对应线段长度恰好为矩形高度的格子表示.

故对于每一个格子, 求出其对应矩阵即可(即其对应线段左右移动的最远地点)

可推得:

up[i][j] = up[i-1][j] + 1, 当格子为障碍物或者边界时, up为0

left[i][j] = max(left[i-1][j], lo+1) 其中lo为当前格子所在行左侧最靠近的障碍坐标.

同理有

right[i][j] = min(right[i-1][j], ro-1)

# include <cstdio>
# include <algorithm>
# define rep(x, n) for (int x = 0; x < n; ++x)
using namespace std;
const int maxn = 1003;

int t;
int n, m;

int a[maxn][maxn];

int up[maxn][maxn], left[maxn][maxn], right[maxn][maxn];

int main()
{
    scanf("%d", &t);
    while ( t-- )
    {
        scanf("%d%d", &n, &m);
        rep(i, n)
            rep(j, m)
            {
                char ch = getchar();
                while ( ch != 'R' && ch != 'F' ) ch = getchar();
                a[i][j] = ch == 'R' ? 1 : 0;
            }
        int ans = 0;
        rep(i, n)
        {
            int lo = -1, ro = m;
            rep(j, m)
                if ( a[i][j] )
                {
                    up[i][j] = left[i][j] = 0;
                    lo = j;
                }
                else
                {
                    up[i][j] = i == 0 ? 1 : up[i-1][j] + 1;
                    left[i][j] = i == 0 ? lo+1 : max(left[i-1][j], lo+1);
                }
            for (int j = m-1; j >= 0; --j )
                if ( a[i][j] == 1 )
                {
                    right[i][j] = m;
                    ro = j;
                }
                else
                {
                    right[i][j] = i == 0 ? ro-1 : min(right[i-1][j], ro-1);
                    ans = max(ans, (right[i][j] - left[i][j] + 1) * up[i][j]);
                }
        }
        printf("%d\n", ans*3);
    }
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>