现在的位置: 首页 > 综合 > 正文

hdu – 2870 – Largest Submatrix(dp / 单调栈)

2019年08月29日 ⁄ 综合 ⁄ 共 2212字 ⁄ 字号 评论关闭

题意:一个由 a, b, c, w, x, y, z 组成的 m 行 n 列(1 ≤ m, n ≤ 1000)的字母矩阵,w 可以转成 a, b,x 可以转成 b, c,y 可以转成 a, c,z 可以转成 a, b, c。问由相同字母组成的最大子矩阵的面积。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2870

——>>依次求a, b, c的最大子矩阵。。

求一个矩阵的最大子矩阵:http://blog.csdn.net/scnu_jiechao/article/details/40677547

#include <cstdio>
#include <cstring>
#include <algorithm>

using std::max;

const int MAXN = 1000 + 10;

int m, n;
int ret;
int h[MAXN];
int L[MAXN], R[MAXN];
char G[MAXN][MAXN];

void Read()
{
    for (int i = 1; i <= m; ++i)
    {
        getchar();
        for (int j = 1; j <= n; ++j)
        {
            G[i][j] = getchar();
        }
    }
}

void Init()
{
    ret = 0;
}

void Dp()
{
    for (int i = 1; i <= n; ++i)
    {
        L[i] = i;
        while (L[i] - 1 >= 1 && h[L[i] - 1] >= h[i])
        {
            L[i] = L[L[i] - 1];
        }
    }
    for (int i = n; i >= 1; --i)
    {
        R[i] = i;
        while (R[i] + 1 <= n && h[R[i] + 1] >= h[i])
        {
            R[i] = R[R[i] + 1];
        }
    }
    for (int i = 1; i <= n; ++i)
    {
        ret = max(ret, (R[i] - L[i] + 1) * h[i]);
    }
}

void GetTargetMax(char target, char c1, char c2, char c3)
{
    memset(h, 0, sizeof(h));
    for (int i = 1; i <= m; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {
            char& x = G[i][j];
            if (x == target || x == c1 || x == c2 || x == c3)
            {
                ++h[j];
            }
            else
            {
                h[j] = 0;
            }
        }
        Dp();
    }
}

void Output()
{
    printf("%d\n", ret);
}

int main()
{
    while (scanf("%d%d", &m, &n) == 2)
    {
        Read();
        Init();
        GetTargetMax('a', 'w', 'y', 'z');
        GetTargetMax('b', 'w', 'x', 'z');
        GetTargetMax('c', 'x', 'y', 'z');
        Output();
    }

    return 0;
}

单调栈实现:

#include <cstdio>
#include <cstring>
#include <algorithm>

using std::max;

const int MAXN = 1000 + 10;

int m, n;
int ret;
int h[MAXN];
int L[MAXN], R[MAXN];
char G[MAXN][MAXN];

struct MS
{
    int st[MAXN];
    int top;

    MS(): top(0) {}

    void Init()
    {
        top = 0;
    }

    void PushMin(const int* A, const int& i)
    {
        while (top != 0 && A[i] <= A[st[top - 1]])
        {
            --top;
        }
        st[top++] = i;
    }

    int Size()
    {
        return top;
    }

    int Second()
    {
        return st[top - 2];
    }
};

void Read()
{
    for (int i = 1; i <= m; ++i)
    {
        getchar();
        for (int j = 1; j <= n; ++j)
        {
            G[i][j] = getchar();
        }
    }
}

void Init()
{
    ret = 0;
}

void Update()
{
    MS ms;
    for (int i = 1; i <= n; ++i)
    {
        ms.PushMin(h, i);
        if (ms.Size() == 1)
        {
            L[i] = 1;
        }
        else
        {
            L[i] = ms.Second() + 1;
        }
    }

    ms.Init();
    for (int i = n; i >= 1; --i)
    {
        ms.PushMin(h, i);
        if (ms.Size() == 1)
        {
            R[i] = n;
        }
        else
        {
            R[i] = ms.Second() - 1;
        }
    }

    for (int i = 1; i <= n; ++i)
    {
        ret = max(ret, (R[i] - L[i] + 1) * h[i]);
    }
}

void GetTargetMax(char target, char c1, char c2, char c3)
{
    memset(h, 0, sizeof(h));
    for (int i = 1; i <= m; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {
            char& x = G[i][j];
            if (x == target || x == c1 || x == c2 || x == c3)
            {
                ++h[j];
            }
            else
            {
                h[j] = 0;
            }
        }
        Update();
    }
}

void Output()
{
    printf("%d\n", ret);
}

int main()
{
    while (scanf("%d%d", &m, &n) == 2)
    {
        Read();
        Init();
        GetTargetMax('a', 'w', 'y', 'z');
        GetTargetMax('b', 'w', 'x', 'z');
        GetTargetMax('c', 'x', 'y', 'z');
        Output();
    }

    return 0;
}

抱歉!评论已关闭.