题解 | 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