洛谷P4147 玉蟾宫(动规:最大子矩形问题/悬线法)

题目链接:传送门

题目大意:

  求由F构成的最大子矩阵的面积。输出面积的三倍。

  1 ≤ N,M ≤ 1000。

思路:

  悬线法模板题。

#include <bits/stdc++.h>

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 init()
{
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++)
            if (mat[i][j] == 'F')
                lef[i][j] = lef[i][j-1] + 1;
            else
                lef[i][j] = 0;
        for (int j = M; j >= 1; j--)
            if (mat[i][j] == 'F')
                rig[i][j] = rig[i][j+1] + 1;
            else
                rig[i][j] = 0;
    }

}

void dp()
{
    int ans = 1;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (mat[i][j] == 'F') {
                if (i > 1 && mat[i-1][j] == 'F') {
                    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;
            }
            else
                up[i][j] = 0;
            int len = rig[i][j] + lef[i][j] - 1;
            int high = up[i][j];
            int a = min(len, high);
            ans = max(ans, a*a);
            ans = max(ans, len*high);
        }
    }
    cout << ans*3 << endl;
}

int main()
{
    cin >> N >> M;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= M; j++)
            cin >> mat[i][j];
    init();
    dp();

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9838141.html