题意:一个由 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; }