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

题目来源于牛客竞赛: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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值