AcWing

https://www.acwing.com/problem/content/154/

悬线法dp,悬线dp,不知道这样对不对,反正能过,看看别人的证明:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int n, m;
int g[1005][1005];
int up[1005][1005];

stack<int> st;
stack<int> st2;

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    //freopen("citygame.in", "r", stdin);
    //freopen("citygame.out", "w", stdout);
    //int T;
    //scanf("%d", &T);
    int T = 1;
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n + 1; ++i) {
            memset(g[i], 0, sizeof(g[i][0]) * (m + 1));
            memset(up[i], 0, sizeof(up[i][0]) * (m + 1));
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m; ++j) {
                char tmp[2];
                scanf("%s", tmp);
                g[i][j] = (tmp[0] == 'F');
            }
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m; ++j)
                up[i][j] = (g[i][j] == 0 ? 0 : up[i - 1][j] + 1);
        }
        int ans = 0;
        for(int i = 1; i <= n; ++i) {
            while(!st.empty()) {
                st.pop();
                st2.pop();
            }
            for(int j = 1; j <= m; ++j) {
                int prej = j;
                while(!st.empty() && up[i][st.top()] > up[i][j]) {
                    ans = max(ans, (j - st2.top()) * up[i][st.top()]);
                    st.pop();
                    prej = st2.top();
                    st2.pop();
                }
                st.push(j);
                st2.push(prej);
            }
            while(!st.empty()) {
                ans = max(ans, (m + 1 - st2.top()) * up[i][st.top()]);
                st.pop();
                st2.pop();
            }
        }
        printf("%d
", ans * 3);
    }
}

纯dp的方法就是这样:预处理每个点向左、向右的扩展距离,然后统一处理向上的扩展距离。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int n, m;
int G[1005][1005];
int U[1005][1005];
int L[1005][1005];
int R[1005][1005];

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    //freopen("citygame.in", "r", stdin);
    //freopen("citygame.out", "w", stdout);
    //int T;
    //scanf("%d", &T);
    int T = 1;
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n + 1; ++i) {
            memset(G[i], 0, sizeof(G[i][0]) * (m + 1));
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m; ++j) {
                char tmp[2];
                scanf("%s", tmp);
                G[i][j] = (tmp[0] == 'F');
            }
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m; ++j) {
                U[i][j] = 1;
                L[i][j] = j;
                R[i][j] = j;
            }
        }

        for(int i = 1; i <= n; ++i) {
            for(int j = 2; j <= m; ++j) {
                if(G[i][j] == 1 && G[i][j - 1] == 1)
                    L[i][j] = L[i][j - 1];
            }
        }

        for(int i = 1; i <= n; ++i) {
            for(int j = m - 1; j >= 1; --j) {
                if(G[i][j] == 1 && G[i][j + 1] == 1)
                    R[i][j] = R[i][j + 1];
            }
        }

        for(int i = 2; i <= n; ++i) {
            for(int j = 2; j <= m; ++j) {
                if(G[i][j] == 1 && G[i - 1][j] == 1) {
                    U[i][j] = U[i - 1][j] + 1;
                    L[i][j] = max(L[i][j], L[i - 1][j]);
                    R[i][j] = min(R[i][j], R[i - 1][j]);
                }
            }
        }

        int ans = 0;
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m; ++j)
                ans = max(ans, U[i][j] * (R[i][j] - L[i][j] + 1));
        }
        printf("%d
", ans * 3);
    }
}
原文地址:https://www.cnblogs.com/Inko/p/11662754.html