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);
}
}