欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

题解 | Second Large Rectangle-2019牛客暑期多校训练营第二场H题

程序员文章站 2022-04-01 12:46:35
...

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss
题目描述:
Given a N×M binary matrix. Please output the size of second large rectangle containing all “1”.

Containing all “1” means that the entries of the rectangle are all “1”.

A rectangle can be defined as four integers x1,y1,x2,y2 where 1≤x1≤x2≤N and 1≤y1≤y2≤M. Then, the rectangle is composed of all the cell (x, y) where x1≤x≤x2 and y1≤y≤y2. If all of the cell in the rectangle is “1”, this is a valid rectangle.

Please find out the size of the second largest rectangle, two rectangles are different if exists a cell belonged to one of them but not belonged to the other.

输入描述:
The first line of input contains two space-separated integers N and M.
Following N lines each contains M characters cij.

1≤N,M≤1000
N×M≥2
cij∈"01"

输出描述:
Output one line containing an integer representing the answer. If there are less than 2 rectangles containning all “1”, output “0”.

示例1:
输入
1 2
01

输出
0

示例2:
输入
1 3
101

输出
1

题解:
• Dynamic Programming
The largest rectangle is a classic problem.
We can solve it in O(NM) by DP.
For each (i, j), we can find out the largest rectangle whose bottom contains (i, j). Suppose it’s X by Y.
Then, we can maintain a sorted list(or heap) containing first several largest rectangle. Actaully, we only need to keep 2!.

• Dynamic Programming
The largest rectangle is a classic problem.
We can solve it in O(NM) by DP.
For a rectangle with size X by Y. We only need to push XY, (X-1)Y, X(Y-1) into the sorted list. And, always resize it into 2 or less items to keep the insertion running in O(1).
Resulting an solution in O(NM).

代码:

// Author: Yen-Jen Wang
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

struct Data {
    int up, down, left, right;

    Data( int _up , int _down , int _left , int _right ) : up(_up), down(_down), left(_left), right(_right) {}

    bool operator == (const Data &rhs) const {
        return (up == rhs.up) && (down == rhs.down) && (left == rhs.left) && (right == rhs.right);
    }
};

vector<Data> vs[1000000 + 7];

int solve(int n, int m, vector<vector<int> > &array) {
    int lo, ro;
    int ans = 0, tmp = 0;
    vector<int> h(m + 1, 0), l(m + 1, 1), r(m + 1, m);

    for (int i = 1; i <= n; i++) {
        lo = 0;
        ro = m + 1;

        for (int j = 1; j <= m; j++) {
            if (array[i][j] == 0)
                h[j] = 0, l[j] = 1, lo = j;
            else
                h[j]++, l[j] = max(l[j], lo + 1);
        }

        for (int j = m; j >= 1; j--) {
            if (array[i][j] == 0)
                r[j] = m, ro = j;
            else {
                r[j] = min(r[j], ro - 1);
                int x = h[j] * (r[j] - l[j] + 1);
                if (x > tmp && x > 0) {
                    int up = i - h[j] + 1, down = i, left = l[j], right = r[j];
                    Data rect = Data(up, down, left, right);
                    vs[x].push_back(rect);
                    ans = max(tmp, max((down - up + 1) * (right - left), (down - up) * (right - left + 1)));
                    tmp = max(tmp, x);
                }
                else if(x > 0) {
                    int up = i - h[j] + 1, down = i, left = l[j], right = r[j];
                    Data rect = Data(up, down, left, right);
                    bool check = true;
                    for (int k = 0; k < (int)vs[x].size(); k++) {
                        if(vs[x][k] == rect) {
                            check = false;
                            break;
                        }
                    }
                    if (check)
                        ans = max(ans, x);
                    ans = max(ans, max((down - up + 1) * (right - left), (down - up) * (right - left + 1)));
                }
            }
        }
    }
    return ans;
}

int read_char() {
    char c;
    for (c = getchar(); !(c == '0' || c == '1'); c = getchar());
    return c - '0';
}

int main() {
    int n , m;
    scanf("%d%d", &n, &m);
	vector<vector<int> > array(n + 1, vector<int>(m + 1));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++)
            array[i][j] = read_char();
    }
	printf("%d\n", solve(n, m, array));
    return 0;
}

更多问题,更详细题解可关注牛客竞赛区,一个刷题、比赛、分享的社区。
传送门:https://ac.nowcoder.com/acm/contest/discuss