POJ 3494 Largest Submatrix of All 1's(最大全1子矩阵面积、单调栈)

题目链接:
POJ 3494 Largest Submatrix of All 1’s
题意:
给出一个 nm 的01矩阵,求出最大全1子矩阵面积。
数据范围: n,m2000
分析:
我们把每一行单独处理,把从这行向上连续延伸全为1的最大长度看成是矩形的高,那么每行其实就是求个最大矩形面积。

height[i][j]:ij1

需要用 O(n2) 的复杂度预处理出 height[] ,然后需要枚举每行,每行利用单调栈可以在 O(n) 复杂度得到最大矩形面积,总的时间复杂度是: O(n2)

#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int MAX_N = 2010;

int n, m, ans;
int mat[MAX_N][MAX_N];
int height[MAX_N][MAX_N], sta[MAX_N], L[MAX_N], R[MAX_N];

//height[i][j]:第i行第j列元素往上最长的连续1长度
//维护单调非递减栈
void solve(int row)
{
    int top = 0, cur;
    height[row][m + 1] = 0;
    for (int j = 1; j <= m + 1; ++j) {
        while (1) {
            cur = sta[top];
            if (height[row][cur] <= height[row][j]) break;
            R[cur] = j;
            --top;
        }
        L[j] = cur;
        sta[++top] = j;
    }
    for (int j = 1; j <= m; ++j) {
        if(mat[row][j] == 0) continue;
        int len = R[j] - L[j] - 1;
        ans = max(ans, height[row][j] * len);
    //  printf("height[%d][%d] = %d len = %d\n", row, j, height[row][j], len);
    }
}

int main()
{
    while (~scanf("%d%d", &n, &m)) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                scanf("%d", &mat[i][j]);
            }
        }
        memset (height, 0, sizeof(height));
        for (int j = 1; j <= m; ++j) {
            for (int i = 1; i <= n; ++i) {
                if (mat[i][j] == 1) {
                    height[i][j] = 1;
                    while (mat[++i][j] == 1) {
                        height[i][j] = height[i - 1][j] + 1;
                    }
                    --i;
                }
            }
        }
        ans = 0;
        for (int i = 1; i <= n; ++i) { solve(i); }
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(POJ,+++单调队列,单调栈)