"ZJOI2007" board production - hanging line method

In a $ N \ times M $ 01 to $ $ matrix, seeking a position adjacent to the largest number of different rectangular and square.

Topic links: BZOJ1057

At first glance, perhaps violence can solve the problem, you can enumerate graphic violence taken long and wide, and then violence enumeration.

But this time complexity of up to $ O (n ^ 2 m ^ 2) $, certainly does not work, and it is difficult to write.

At this time, we have introduced "hanging line method."

 For each position, we pre-longest upward out of this node can be extended to apply legal length $ left $.

An array of pre-treatment and then the other node can be a maximum downward extension application legitimate length $ right $.

Processing matrix and then laterally, the lateral length is determined at each point the maximum value is valid, the connection with a line.

Known as the "hanging line." Obtaining a position farthest suspended line can be extended to up and down, the suspension line is a trajectory under the legal sub-matrix,

And the sub-matrix of the top, left, bottom can not be extended. If it can extend to the right, then in the next enumeration, the resulting matrix can be extended to enumerate, otherwise it is a great legal sub-matrix.

Time complexity $ (nm) O $

code show as below

#include <stdio.h>
#include <algorithm>
int n, m;
int qrt(int x)
{
    return x * x;
}
int pe[2005][2005], b[2005][2005], c[2005][2005];
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            scanf("%d", &pe[i][j]);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (j == 1 || pe[i][j] == pe[i][j - 1])
                b[i][j] = 1;
            else
            {
                b[i][j] = b[i][j - 1] + 1;
            }
        }
        for (int j = m; j >= 1; j--)
        {
            if (j == m || pe[i][j] == pe[i][j + 1])
                c[i][j] = 1;
            else
            {
                c[i][j] = c[i][j + 1] + 1;
            }
        }
    }
    int sq_max = 0, rec_max = 0;
    for (int j = 1; j <= m; j++)
    {
        int up = 0, left = 0, right = 0;
        for (int i = 1; i <= n; i++)
        {
            if (i == 1 || pe[i][j] == pe[i - 1][j])
            {
                up = 1;
                left = b[i][j];
                right = c[i][j];
            }
            else
            {
                up++;
                left = std::min(left, b[i][j]);
                right = std::min(right, c[i][j]);
            }
            rec_max = std::max(rec_max, up * (left + right - 1));
            sq_max = std::max(sq_max, qrt(std::min(left + right - 1, up)));
        }
    }
    printf("%d\n%d\n", sq_max, rec_max);

    return 0;
}

 

Guess you like

Origin www.cnblogs.com/bestcoder-Yurnero/p/11235667.html