《深入浅出进阶篇》洛谷P4147 玉蟾宫——悬线法dp

上链接:P4147 玉蟾宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P4147

上题干:

有一个NxM的矩阵,每个格子里写着R或者F。R代表障碍格子,F代表无障碍格子请找出其中的一个子矩阵,其元素均为‘F’,并且面积最大,输出它的面积*3的值

求最大子矩阵我们一般用到一个方法叫——悬线法;

下面来介绍悬线法:

我们找任意找一个非障碍格子作为底边的一个格子,从该点出发,引出3条直线,左直线,右直线,上直线。

我们从这个点出发,向左一直延伸直到遇到障碍格,向右一直延伸一直延长到障碍格子,同理,向上也是。

第一步:

设置四个数组:

棋盘:char a[N][N];

左悬线数组:表示每个格子能向左延伸到的最远距离, int l[N][N];

右悬线 :表示每个格子能向右延伸到的最远距离,int r[N][N] ;

上悬线:表示每个格子能向上延伸到的最远距离 int h[N][N];

第二步:

求左悬线:

思路:

我们先将每个格子的向左能延伸到的最远距离初始化为该格子本身的列数,也就是它一开始只能延伸到它本身。

以第一行为例:

然后循环每一列,从最左边开始,当a[i][j]为空地,并且a[i][j-1]为空地的时候,该格子的左悬线能延伸到的位置就是左边一格能延伸到的位置。

所以有此代码:

	
for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++)
		if (a[i][j] == 'F' and a[i][j - 1] == 'F')l[i][j] = l[i][j - 1];

这样就可以求出所有格子的左悬线了。

同理

求右悬线:

思路:

我们先将每个格子的向右能延伸到的最远距离初始化为该格子本身的列数,也就是它一开始只能延伸到它本身

循环每一列,从最右边开始,当a[i][j]为空地,并且a[i][j+1]为空地的时候,该格子的右悬线能延伸到的位置就是右边一格能延伸到的位置。

 

for (int i = 1; i <= n; i++)
	for (int j = m; j >= 1; j--)
		if (a[i][j] == 'F' and a[i][j + 1] == 'F')r[i][j] = r[i][j + 1];

求上悬线:

思路:

我们先将每个格子的向上能延伸到的最远距离初始化为该格子本身的高度,即为1,也就是它一开始只能延伸到它本身

循环每一列,从任意一遍开始都行,我们以从左边开始为例子,当a[i][j]为空地,并且a[i-1][j]为空地的时候,该格子的上悬线能延伸到的位置就是上边一格能延伸到的位置。

for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++)
		if (a[i][j] == 'F' and a[i - 1][j] == 'F')h[i][j] = h[i - 1][j] + 1;

将这三个代码整合起来就是这样的:

for (int i = 1; i <= n; i++)
{
	for (int j = 1; j <= m; j++)
		if (a[i][j] == 'F' and a[i][j - 1] == 'F')l[i][j] = l[i][j - 1];
	for (int j = m; j >= 1; j--)
		if (a[i][j] == 'F' and a[i][j + 1] == 'F')r[i][j] = r[i][j + 1];
	for (int j = 1; j <= m; j++)
		if (a[i][j] == 'F' and a[i - 1][j] == 'F')h[i][j] = h[i - 1][j] + 1;
}

第三步:

求每个格子以上悬线为高的矩形面积

到这里还没有结束,不要傻乎乎的就用每一个格子的三个悬线开始计算面积了。

我们应该可以注意到,有这样一种情况:

如果直接拿右悬线-左悬线 乘以高的话,求出来的面积 是绿色矩形的面积,然而实际上我们希望求的是在上悬线尽可能高的情况下的矩形面积(目的是使得枚举不重不漏)。

所以我们还需要修改一个条件,该格的左悬线应该为 (该格,和上面一格)的左悬线之间长度小的那一根。

由于l[i][j]代表的是该格向左能延伸到的最远的坐标(离得越远,坐标越小),所以我们需要让l[i][j]尽可能大,

同理,我们要让r[i][j]尽可能的小。

那么则有:

for (int i = 1; i <= n; i++)
	for (int j = 1; j <= m; j++) 
		if (a[i][j] == 'F' and a[i - 1][j] == 'F') {
			r[i][j] = min(r[i][j], r[i - 1][j]);
			l[i][j] = max(l[i][j], l[i - 1][j]);
          }

到这里就基本结束了。

第四步:

最后我们只需要打擂台,不断求出每个格子三悬线组成的面积的最大值就可以了。

也就是: 

for (int i = 1; i <= n; i++)	
	if (a[i][j] == 'F')
		ans = max(ans, h[i][j] * (r[i][j] - l[i][j] + 1));

总的来看,这道题一共有四个步骤,设三条悬线,求三条悬线,求以上悬线为高的矩形面积,打擂台求最大值。

上代码:


const int N = 1010;
int n, m, ans;
char a[N][N];
int h[N][N], l[N][N], r[N][N];
int main()
{
	ans = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
		{
			cin >> a[i][j];
			h[i][j] = 1, r[i][j] = l[i][j] = j;//初始化h,r,l
		}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
			if (a[i][j] == 'F' and a[i][j - 1] == 'F')l[i][j] = l[i][j - 1];
		for (int j = m; j >= 1; j--)
			if (a[i][j] == 'F' and a[i][j + 1] == 'F')r[i][j] = r[i][j + 1];
		for (int j = 1; j <= m; j++)
			if (a[i][j] == 'F' and a[i - 1][j] == 'F')h[i][j] = h[i - 1][j] + 1;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++) {
			if (a[i][j] == 'F' and a[i - 1][j] == 'F') {
				r[i][j] = min(r[i][j], r[i - 1][j]);
				l[i][j] = max(l[i][j], l[i - 1][j]);
			}
			if (a[i][j] == 'F')
				ans = max(ans, h[i][j] * (r[i][j] - l[i][j] + 1));
		}
	}
	cout << 3 * ans;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/142788.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

金蝶云星空设置单据体行高

文章目录 金蝶云星空设置单据体行高表单插件Python脚本 金蝶云星空设置单据体行高 表单插件 新建类继承AbstractBillPlugIn&#xff0c;重写OnInitialize方法进行设置 public override void OnInitialize(InitializeEventArgs e){base.OnInitialize(e);this.View.GetControl&…

卡尔曼滤波器第 1 部分 - 简介

一、说明 这是卡尔曼滤波器系列的第一部分。但这并不是另一本定义繁重的读物&#xff0c;它会给你带来一堆行话和方程式&#xff01;在本文中&#xff0c;我们首先关注需要解决方案的问题&#xff08;当然是卡尔曼滤波器&#xff09;&#xff0c;然后直观地了解卡尔曼滤波器。只…

CDN加速技术:节点部署的专业指南

随着互联网的迅猛发展&#xff0c;网站的访问量也在不断增加。为了提供更快、更稳定的用户体验&#xff0c;许多网站都采用了剑盾上云CDN&#xff08;内容分发网络&#xff09;技术。在CDN加速中&#xff0c;节点的合理部署是关键一环&#xff0c;决定了加速效果的优劣。本文将…

美国通胀预期高企,现货黄金价格继续承压下滑

上周五现货黄金持续振荡下滑&#xff0c;金价失守1940美元关口&#xff0c;最低至1933.17美元/盎司&#xff0c;最终收跌1.09%&#xff0c;报1936.51美元/盎司&#xff0c;创10月17日以来新低&#xff1b;今日&#xff08;周一&#xff09;截止汉声集团分析师发稿前&#xff0c…

python趣味编程-使用 Tkinter 的数字到单词转换器

数字到单词转换器应用程序是用Python编程语言编写的。该项目包含演示数字到单词转换的编码脚本。在 Python 中使用 Tkinter 的数字到单词转换器应用程序是一个应用程序,其主要目的是将您输入的数字转换为单词。数字到单词转换器应用程序提供学习资源,帮助您更好地了解Python编…

【python自动化】Playwright基础教程(五)事件操作②悬停输入清除精讲

【python自动化】Playwright基础教程(五)事件操作②悬停&输入&清除精讲 本章目录 文章目录 【python自动化】Playwright基础教程(五)事件操作②悬停&输入&清除精讲鼠标悬停 - hover鼠标悬停实战 输入内容 - fill输入内容实战清空内容实战 输入内容 - type模拟…

CSS省略号n行公式

记得改图中的n&#xff0c;这是你需要的几行省略号&#xff01;复制中间的5行就行了。 .text {overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: n; //n为你想省略的行数&#xff0c;需要改-webkit-box-orient: vertical; } 这是…

单链表(8)

单链表的特点 可以发现&#xff0c;在单链表的for循环里&#xff0c;初始化就总结为这两种情况 上图中 用第一条&#xff08;要改变链表的结构&#xff0c;增加&#xff0c;减少结点个数等&#xff09;的有&#xff1a;尾插&#xff0c;插入&#xff0c;删除pos位置值&#x…

应用开发平台集成表单设计器系列之2——深入了解与技术验证

背景 上一篇&#xff0c;对表单设计器进行了技术预研&#xff0c;在三款组件form-generator、FormMaking、form-create-designer中初步选择了form-create-designer&#xff0c;接下来的工作&#xff0c;是需要深入了解&#xff0c;进行技术验证&#xff0c;确保该组件功能基本…

安防视频监控EasyCVR平台使用海康ehome接入,配置信息不对是什么原因?该如何将解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

VMware ubuntu 新虚拟机的创建

根据自己指定的路径安装好vm后。 创建新的虚拟机。 记录一下&#xff0c;下次用到别再忘记了。 如需转载&#xff0c;注明出处&#xff01; 点赞收藏关注我 以资鼓励 打开vm 软件&#xff0c;点击创建新的虚拟机 选择典型&#xff0c;点击下一步 选择你的ubuntu镜像iso文件 …

【算法训练-链表 零】链表高频算法题看这一篇就够了

一轮的算法训练完成后&#xff0c;对相关的题目有了一个初步理解了&#xff0c;接下来进行专题训练&#xff0c;以下这些题目就是汇总的高频题目 题目题干直接给出对应博客链接&#xff0c;这里只给出简单思路、代码实现、复杂度分析 反转链表 依据难度等级分别为反转链表、…

Window安装MongoDB

三种NOSQL的一种,Redis MongoDB ES 应用场景: 1.社交场景:使用Mongodb存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人,地点等功能 2.游戏场景:使用Mongodb存储游戏用户信息,用户的装备,积分等直接以内嵌文档的形式存储,方便查询,高效率存储和访问…

Python 如何实现访问者设计模式?什么是访问者(Visitor)模式?实际案例中有什么作用?

什么是访问者设计模式&#xff1f;访问者&#xff08;Visitor&#xff09;设计模式介绍&#xff1a; 访问者&#xff08;Visitor&#xff09;设计模式是一种行为设计模式&#xff0c;用于在不修改被访问对象的前提下定义新的操作。它通过将操作封装到独立的访问者类中&#xf…

JumpServer管理虚拟机

环境准备 1.虚拟机192.168.1.111在线安装JumpServer https://blog.csdn.net/tongxin_tongmeng/article/details/1340166222.虚拟机192.168.1.112创建用户changwq、wangwj useradd changwq && passwd changwq、useradd wangwj && passwd wangwj3.虚拟机192.168.…

springboot容器

1.主要指的是servlet容器 servlet组件由sevlet Filter Listener等 2.自动配置原理 通过ServletWebServerFactoryAutoConfiguration 配置这些内容 (自动配置类开始分析功能) conditionalOnclass开启条件 ServletRequest类 import导入嵌入式的tomcat Jetty等 这些是配置类&…

本地化工具:Soluling Localization Crack

Soluling 是一个本地化工具&#xff0c;包含本地化项目所需的所有功能。Solling 使本地化变得非常容易。Soluling 是桌面应用程序和命令行工具的组合 。Solling支持100多种文件格式。通过 Soluling&#xff0c;您可以本地化桌面应用程序、移动应用程序、Web 应用程序、文档和在…

如何在thingsboard的规则链中对一个遥测属性进行求平均值

背景 有这样一个需求,一个温度传感器每5秒,上传一次数据。要求算出该设备2分钟内的平均温度,如果超过某个值,则发送告警邮件。 具体操作实现 下面在规则链中实现求平均值。 使用的节点是 配置如下 必填 Timeseries keys,是要求的平均值的属性名。 我这里求的是四个…

【教学类-17-03】20231105《世界杯随机参考图七巧板 3份一页》(大班)

效果展示&#xff1a; 单页效果 多页效果 预设样式&#xff1a; 背景需求&#xff1a; 2022年11月24日&#xff0c;大1班随机抽取的9位幼儿制作了9张拼图&#xff0c;发现以下三个问题&#xff1a; 1、粉红色辅助纸选择量多——9份作业有4位幼儿的七巧板人物是粉红色的 2、…

嵌入式杂记 -- MCU的大小端模式

MCU的大小端模式 大端模式小端模式大小端模式测试联合体概念MCU大小端模式测试大端模式测试小端模式测试 大小端模式转换 在进行MCU开发的时候&#xff0c;我们需要注意MCU的数据存储模式&#xff0c;在嵌入式中有两种不同的存储模式&#xff0c;分别是 大端模式和小端模式。 …