《深入浅出进阶篇》洛谷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;}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Cocos新手进阶】通过cocos实现可控制的动态加载更新的日志界面效果

本篇文章主要讲解&#xff0c;通过cocos实现可控制的动态加载更新的日志界面效果。 日期&#xff1a;2023年11月15日 作者&#xff1a;任聪聪 效果演示&#xff1a; 效果说明&#xff1a;在一个界面可以动态输出for循环的结果并更新到界面中进行不断加载的日志页面效果&#x…

Java 算法篇-链表的经典算法:根据值删除节点、删除倒数第 n 个节点

&#x1f525;博客主页&#xff1a; 小扳_-CSDN博客 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 链表的创建 2.0 链表的经典算法 - 根据值来删除节点 2.1 根据值来删除节点 - 遍历链表来实现 2.2 根据值来删除节点 - 递归实现 3.0 链表的经典算法 - 删除倒数第 n…

前端element的el-tooltip鼠标经过显示文字,没有文字显示空黑框问题

场景&#xff1a; 有时候在使用element的el-tooltip时会使用三元表达式&#xff0c;满足某个条件后才显示提示文字&#xff0c;否则不展示文字&#xff0c;但是却出现在在没有文字时展示了黑框&#xff0c;如下图&#xff1a; 解决方案&#xff1a; 加一个disabled便可&#…

Spring Cloud Netflix微服务组件-Eureka

CAP理论 分区容忍是能容忍一个或一部分节点挂掉后&#xff0c;整体系统也能正常工作&#xff08;就是别的节点还是活着的&#xff09;&#xff0c;所以分布式系统中P是必须要有的。比如数据库主从架构&#xff0c;主从两个节点之间需要数据同步&#xff0c;主挂了&#xff0c;…

最新PS 2024 虎标正式版来啦,附带AI神经滤镜(支持win/mac)

软件简介 文件名称 PS2024 虎标正式版 支持系统 windows、Mac 获取方式 文章底部 分享形式 百度网盘 小伙伴们&#xff0c;下午好&#xff01;今天给大家的是PS 2024 25.0虎标正式版。 PS 2024 25.0 正式版介绍 经历了多次Photoshop 2023 Beta 测试之后&#xff0c;今天…

Qt高级--(2)自定义标题栏

自定义标题栏 功能点 1.标题栏中最外层布局器使用水平布局器。 2.导航按钮、工具按钮和窗口功能按钮都是用水平布局器&#xff0c;边距和间隔可根据实际情况设置。 3.编写 QSS 样式&#xff0c;并将样式设置到窗口控件中。 4.实现最小化、最大化和关闭窗口按钮功能。 5.实现鼠…

springboot整合vue2实现简单的新增删除,整合ECharts实现图表渲染

先看效果图&#xff1a; 1.后端接口 // 查询所有商品信息 // CrossOrigin(origins "*")RequestMapping("/list1")ResponseBodypublic List<Goodsinfo> list1(){List<Goodsinfo> list goodsService.list();return list;}// 删除 // …

你绝对需要的Facebook养号攻略,教你如何养成耐用号

Facebook 可谓是大家的“老熟人”了&#xff0c;作为全球热门的社交媒体平台&#xff0c;Facebook 一直以来都是社媒营销、跨境电商的重要阵地&#xff0c;但是很多小伙伴们在注册新账号后往往忽略了一个重要的步骤&#xff0c;也是必不可少的一步&#xff0c;那就是养号&#…

【跨境电商独立站新手入门手册】

一直想要更新一个独立站的系列合集&#xff0c;用小白也看得懂的方式阐述怎么从0到1搭建并运营一个独立站&#xff0c;并且后续我也会录制成视频。 今天&#xff0c;它来了。 这是《跨境电商独立站新手入门手册》系列的第一篇。 你是否有过这样的经历&#xff1a;当你在网上浏…

vue中使用iconfont图标

1. 选择一个图标加入购物车 2、点击右上角购物车图标。点击下载代码&#xff0c;并添加至项目。 3、将下载好的代码文件放入项目中的assets目录的styles下 iconfont.css直接放在styles下 在styles目录下新建目录iconfont&#xff0c;将iconfont.ttf、iconfont.woff、iconfont…

python自动化测试selenium核心技术3种等待方式详解

这篇文章主要为大家介绍了python自动化测试selenium的核心技术三种等待方式示例详解&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步早日升职加薪 UI自动化测试过程中&#xff0c;可能会出现因测试环境不稳定、网络慢等情况&a…

安防监控系统EasyCVR平台调用hls地址生成流的时间过长,该如何解决?

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