HDU4328 Cut the cake(动规:最大子矩形问题/悬线法)

题目链接:传送门

题目大意:

  给出N*M的字符矩阵(由字符B/R组成),求符合下图条件的子矩阵的最大周长。

  1 ≤ N,M ≤ 1000。

                       

思路:

  悬线法。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
const int MAX_N = 1e3 + 5;

int N, M;
char mat[MAX_N][MAX_N];
int lef[MAX_N][MAX_N], rig[MAX_N][MAX_N], up[MAX_N][MAX_N];

void init1()
{
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++)
            if (j > 1 && mat[i][j] == mat[i][j-1])
                lef[i][j] = lef[i][j-1] + 1;
            else
                lef[i][j] = 1;
        for (int j = M; j >= 1; j--)
            if (j < M && mat[i][j] == mat[i][j+1])
                rig[i][j] = rig[i][j+1] + 1;
            else
                rig[i][j] = 1;
    }
}

void init2()
{
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++)
            if (j > 1 && mat[i][j] != mat[i][j-1])
                lef[i][j] = lef[i][j-1] + 1;
            else
                lef[i][j] = 1;
        for (int j = M; j >= 1; j--)
            if (j < M && mat[i][j] != mat[i][j+1])
                rig[i][j] = rig[i][j+1] + 1;
            else
                rig[i][j] = 1;
    }
}

int dp1()
{
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (i > 1 && mat[i][j] == mat[i-1][j]) {
                up[i][j] = up[i-1][j] + 1;
                lef[i][j] = min(lef[i][j], lef[i-1][j]);
                rig[i][j] = min(rig[i][j], rig[i-1][j]);
            }
            else
                up[i][j] = 1;
            int len = lef[i][j] + rig[i][j] - 1;
            int high = up[i][j];
            ans = max(ans, 2*len+2*high);
        }
    }
    return ans;
}

int dp2()
{
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (i > 1 && mat[i][j] != mat[i-1][j]) {
                up[i][j] = up[i-1][j] + 1;
                lef[i][j] = min(lef[i][j], lef[i-1][j]);
                rig[i][j] = min(rig[i][j], rig[i-1][j]);
            }
            else
                up[i][j] = 1;
            int len = lef[i][j] + rig[i][j] - 1;
            int high = up[i][j];
            ans = max(ans, 2*len + 2*high);
        }
    }
    return ans;
}

int main()
{
    int T;
    int kase = 1;
    cin >> T;
    while (T--) {
        cin >> N >> M;
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= M; j++)
                cin >> mat[i][j];
        int ans = 1;
        init1();
        ans = max(ans, dp1());
        init2();
        ans = max(ans, dp2());
        printf("Case #%d: %d
", kase++, ans);
    }
    return 0;
}
/*
2
3 3
BBR
RBB
BBB
1 1
B
*/
View Code
原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9838212.html