『单调栈』2019牛客暑期多校训练营(第二场)Second Large Rectangle

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
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值