https://ac.nowcoder.com/acm/contest/882/H
题意: 给一个只有‘0’和‘1’的矩形,找到次大的全是‘1’的矩形,两个矩阵只要存在一个‘1’是属于A矩形而不属于B矩形 那么A和B就是不同的矩形
思路: 先使用单调栈求出最大子矩形,然后将这个最大子矩形的高hh,左边距离最近的点位置ll,右边距离最近的点位置rr,所在行ii记录下来,然后遍历一遍全图找到忽略已找到最大子矩形的最大子矩形,此时找到的就是次大子矩形。
最大子矩形的单调栈做法:https://blog.csdn.net/zuzhiang/article/details/78693421
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
const int Max = 1010;
int n, m;
char maze[Max][Max];
int maxx = 0;
int dp[Max][Max] = {0},maze1[Max][Max] = {0};
int l[Max][Max]={0},r[Max][Max]={0};
int main() {
while(scanf("%d %d",&n,&m) != EOF) {
int hh,ll,rr,ii;
memset(dp,0,sizeof(dp));
memset(maze1,0,sizeof(maze1));
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
maxx = 0;
for (int i = 1; i <= n; i++) {
getchar();
for (int j = 1; j <= m; j++) {
scanf("%c", &maze[i][j]);
if (maze[i][j] == '1')
dp[i][j] = dp[i - 1][j] + 1;
}
}
for (int i = 1; i <= n; i++) {
int sta[Max];
int top_ = 0;
for(int j = 1; j <= m ; j++) {
while(top_ && dp[i][sta[top_]] >= dp[i][j]) top_--;
l[i][j] = top_ == 0 ? 0 : sta[top_];
sta[++top_] = j;
}
top_ = 0;
for(int j = m; j > 0 ; j--) {
while(top_ && dp[i][sta[top_]] > dp[i][j]) top_--;
r[i][j] = top_ == 0 ? m +1: sta[top_];
sta[++top_] = j;
}
for(int j = 1; j <= m; j++) {
if(!dp[i][j])
continue;
maze1[i][j] = dp[i][j]*(r[i][j]-l[i][j]-1);
if(maxx < maze1[i][j]) {
hh = dp[i][j];
ll = l[i][j];
ii = i;
rr = r[i][j];
maxx = maze1[i][j];
}
}
}
int sec = 0;
sec=max(sec,hh*(rr-ll-2));
sec=max(sec,(hh-1)*(rr-ll-1));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(hh == dp[i][j] && ii == i && ll == l[i][j] && rr == r[i][j])
continue;
sec = max(sec,maze1[i][j]);
}
}
printf("%d\n",sec);
}
return 0;
}
/*
4 5
10100
10111
11111
10010
*/