线性dp之悬线法学习笔记

悬线法

以前写过求最大正方形面积的题目,这只要处理 [i-1][j],[i][j-1],[i-1][j-1] 三个位置的最小值就可以,用不到悬线法,简单的线性dp;

但是当要求最大长方形时,那种方法就不适合了,悬线法就出现了;

模板题: P4147 玉蟾宫

悬线法可以分为三个部分:

  1. l[i][j] 代表位置 (i,j) 可以往左扩展的最小坐标,就是最远的坐标
  2. r[i][j] 代表位置 (i,j) 可以往右扩展的最大坐标,就是最远的坐标
  3. up[i][j] 代表位置 (i,j) 可以往上扩展的最大距离,不是坐标了

l,r 数组都要进行预处理,最关键的是在进行dp时,l 数组要取最大值,r 数组要取最小值,up 数组加 1 ,就跟求最大正方形面积的思路是一样的,要保证最短的也符合条件;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=1100;
const int M=50100;
const int mod=1e9;
int n,m,a[N][N];
int l[N][N],r[N][N],up[N][N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char c;cin>>c;
			if(c=='F') a[i][j]=1;	
			up[i][j]=1,l[i][j]=r[i][j]=j;
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=2;j<=m;j++){
			if(a[i][j]&&a[i][j-1]) l[i][j]=l[i][j-1];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=m-1;j>=1;j--){
			if(a[i][j]&&a[i][j+1]) r[i][j]=r[i][j+1]; 
		}
	}
	int ans=0;
	for(int i=2;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]&&a[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]+1;	
			}
			ans=max(ans,(r[i][j]-l[i][j]+1)*up[i][j]);
		}
	}
	cout<<ans*3<<endl; 
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值