洛谷 题解 P4417 【[COCI2006-2007#2] STOL】(土豪聪要请客)-悬线法

前言:其他题解的解释都那么少,于是我决定发一篇 悬线法 题解

题目大意

给你一个包括X和.的矩阵,让你求出边长最大的不包括X的矩阵

解题思路

动态规划——悬线法

定义:悬线法可以在 O(nm) 的时间复杂度内解决:给定一个NxM的 01矩阵,其面积最大的子矩阵,使得这个子矩阵中的每一位的值都为0或1

时间当然比单调栈要慢很多,但是代码好写就是个板题

需要定义额外的三个数组

left[i][j],right[i][j]和up[i][j]

分别代表当前点(i,j)所能扩展的最左列,最右列和上面可扩展的的最大长度

如何得出这三个数组?

  1. 初始化,在输入矩阵时,我们就把left和right数组记录当前的列数,up数组记为1
l[i][j]=r[i][j]=j;
up[i][j]=1;
  1. 我们扫两遍矩阵,一次从前往后扫得到left数组,如果当前列和前一列都为.,那么当前列的left数组就从前一列转移来

考虑为什么?

  • 考虑left数组的意义,记录最左可到达的列数

  • 我们在初始化时就把left数组记为当前列数,如果这一列和上一列都可以摆放桌子,那么我们当前就可以记录上一列,而上一列同样也是如此记录的,所以我们可以这样递推

for(re i=1;i<=n;i++)
	for(re j=2;j<=m;j++)
		if(a[i][j]==a[i][j-1]&&a[i][j]=='.')
			l[i][j]=l[i][j-1];

然后right数组同理,倒着推一遍就可以了

for(re i=1;i<=n;i++)
	for(re j=m-1;j>0;j--)
		if(a[i][j]==a[i][j+1]&&a[i][j]=='.')
			r[i][j]=r[i][j+1];

最后,AC代码双手奉上(代码中有详细解释)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define re register int
#define N 1010
using namespace std;
char a[N][N]; int n,m,ans;
int l[N][N],r[N][N],up[N][N];
int main() {
    scanf("%d%d",&n,&m);
    for(re i=1;i<=n;i++) {
        for(re j=1;j<=m;j++) {
            cin>>a[i][j];//初始化
            l[i][j]=r[i][j]=j;
            up[i][j]=1;
        }
    }
    for(re i=1;i<=n;i++)
        for(re j=2;j<=m;j++)
            if(a[i][j]==a[i][j-1]&&a[i][j]=='.')
                l[i][j]=l[i][j-1];//求left数组
    for(re i=1;i<=n;i++)
        for(re j=m-1;j>0;j--)
            if(a[i][j]==a[i][j+1]&&a[i][j]=='.')
                r[i][j]=r[i][j+1];//求right数组
    for(re i=1;i<=n;i++) {
        for(re j=1;j<=m;j++) {//不能是第一列,并且都可以放桌子
            if(i>1&&a[i][j]==a[i-1][j]&&a[i][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;
            }
            int a=r[i][j]-l[i][j]+1;//a是长
            ans=max(ans,a*2+up[i][j]*2);//up[i][j]是当前的宽
        }
    }
    printf("%d",ans-1);//因为自己不算人
    return 0;
}

悬线法题目推荐:P1169 [ZJOI2007]棋盘制作 P4147 玉蟾宫 P2701 [USACO5.3]巨大的牛棚Big Barn

后言:悬线法我昨天晚上刚学,今天模拟赛第二题就出了,因为我急着在lsc大佬前面作对一道题,所以没算空间,内存超限,整个人炸裂

点个赞再走好吗

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值