【试炼场】棋盘制作 【矩阵DP】【悬线法】

传送门

题目大意

给出一个N*M的矩阵,格子有黑白两种颜色,现在要找到黑白相间的、面积最大的矩形和正方形,输出它们的面积。
N,M <= 2000。

题解

对于在某个矩阵中求出满足要求的子矩阵,我们有一种常用方法——悬线法。
其实我不知道为什么起这个名字

这种方法的主要思路是逐个处理,按列继承。对本题而言,我们的思路如下:

①逐个处理:用单调栈的方式,求出每一个点在满足要求的前提下,向左/右最多能延伸到哪一格:

	for(rint i=1;i<=n;i++){
		for(rint j=1;j<=m;j++){
			b[i][j]=rad();
			l[i][j]=r[i][j]=j;
			up[i][j]=1;
		}
	}
	for(rint i=1;i<=n;i++){
		for(rint j=2;j<=m;j++){
			if(b[i][j]!=b[i][j-1])
			l[i][j]=l[i][j-1];
			左边最远
		}
	}
	for(rint i=1;i<=n;i++){
		for(rint j=m-1;j>=1;j--){
			if(b[i][j]!=b[i][j+1])
			r[i][j]=r[i][j+1];
			右边最远
		}
	}

②按列继承:再扫描一次矩阵,这一次我们除了考虑左右的限制,还要考虑上下的限制。为了方便处理,我们从上往下扫,求出每一格向上最多能延伸到多高。

	for(rint i=1;i<=n;i++){
		for(rint j=1;j<=n;j++){
			if(i!=1&&b[i][j]!=b[i-1][j]){
				l[i][j]=max(l[i][j],l[i-1][j]);
				r[i][j]=min(r[i][j],r[i-1][j]);
				up[i][j]+=up[i-1][j];
			}	
			int a1=min(up[i][j],r[i][j]-l[i][j]+1);
	    	ans1=max(ans1,up[i][j]*(r[i][j]-l[i][j]+1));/最大矩形
	    	ans2=max(ans2,a1*a1);/最大正方形
		}	
    }

注意,在这个过程中,我们会为了扩展高度而牺牲宽度,因此要每处理一格就更新一次答案。

然后这道题就圆满解决了~

一点点扩(jing)展(yan)

用悬线法解决最大子矩形的题貌似都很方便,比如 P4147 玉蟾宫P1387 最大正方形
(貌似就是本题1、2问拆开2333)

用类似的思路还可以解决 P1736 创意吃鱼法,本质上都是对从每个点统计扩展到对行和列的统计吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值