【每日一题】逃离火灾

news2024/11/24 14:51:00

文章目录

Tag

【二分答案】【BFS】【数组】【2023-11-09】


题目来源

2258. 逃离火灾


题目解读

现在有一个人在一个二维网格的左上角,坐标 (0, 0) 处,他想安全的到达位于网格右下角 (m-1, n-1) 处的安全屋,其中 m 为网格的行数,n 为网格的列数。

网格的每个格子中有以下三种数值:

  • 0 表示草地;
  • 1 表示着火的格子;
  • 2 表示一座墙,人和火都不能通过。

人每一分钟可以向相邻的格子行走,火可以向相邻的格子扩散,人和火都会被墙阻挡(也就是有墙的格子,人和火都无法到达)。现在需要你判断人在初始位置最多停留多长时间再出发可以安全到达安全屋。如果无法实现,请返回 -1。如果不管停留多长时间,人总是可以到达安全屋,请你返回 1 0 9 10^9 109


解题思路

方法一:二分枚举

我们可以使用二分枚举答案来解决该题。

为什么可以二分枚举答案?单调性如何保证?

如果人可以在初始位置停留 t 分钟,那么肯定可以停留至少 t 分钟;如果人不能在初始位置停留 t 分钟,那么可以停留的时间肯定不能超过 t 分钟。于是可以想到二分枚举答案,如果人可以在初始位置停留 t 分钟,那么接下来就在 t 的右侧进行枚举,否则在 t 的左侧进行枚举。我们通过函数 check() 来判断停留 t 分钟是否安全。

二分枚举答案的上限是什么?

如图,火可能要绕很多圈才能到达左上角,人可以在被火烧到的前一分钟出发。所以粗略估计,就用 m*n 当作二分的上限。

check() 如何实现?

假设当前二分枚举的答案是 t。不管是火的扩散还是人的行走都可以使用 BFS 来实现。

人在前往安全屋之前停留 t 分钟,在这 t 分钟内火向四周扩散。接着在每分钟内人先移动,火再移动,如果人遇到着火的格子那就跳过,不走这个格子。

如果,人最后可以到达安全屋,则说明答案至少为 t,否则答案小于 t

二分枚举逻辑代码

二分的下限 left0。上限 right 前面已经分析了是 mn。答案 res 初始化为 -1

[left, right] 中进行迭代二分,while(left <= right)

  • mid = (left + right) / 2
  • 如果 check(mid)true,则更新 res = midleft = mid + 1;否则更新 right = mid - 1
  • 最后返回 left

最终的答案还要比较一下 res 是否小于 m*n,如是返回 left,否则返回 1 0 9 10^9 109

实现代码

class Solution {
    const int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

public:
    bool check(vector<vector<int>>& grid, int t) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>>on_fire(m, vector<int>(n));  // 记录着火的格子
        vector<pair<int, int>> f;                       // 两个数组来代替队列
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 1) {
                    on_fire[i][j] = 1;
                    f.emplace_back(i, j);               // 或者 f.push_back({i, j});
                }
            }
        }

        // 火扩散的 BFS
        auto spread_fire = [&]() {
            vector<pair<int, int>> nf;                  // f 和 nf 配合取代队列
            for (auto& [i, j] : f) {
                for (auto& [dx, dy] :dirs) {
                    int x = i + dx, y = j + dy;
                    if (0 <= x && x < m && 0 <= y && y < n && !on_fire[x][y] && grid[x][y] == 0) {
                        on_fire[x][y] = 1;
                        nf.emplace_back(x, y);
                    }
                }
            }
            f = move(nf);
        };

        // t 分钟内火向四周扩散
        while (t -- && !f.empty()) {
            spread_fire();
        }

        if (on_fire[0][0]) return false;                  // 初始位置着火

        // 人和火先后扩散
        vector<vector<int>> vis(m, vector<int>(n));       // 防止人重复走同一个格子
        vis[0][0] = 1;
        vector<pair<int, int>> q{{0, 0}};
        while (!q.empty()) {
            vector<pair<int, int>> nq;
            for (auto& [i, j] : q) {
                if (on_fire[i][j]) continue;
                for (auto& [dx, dy] : dirs) {
                    int x = i + dx, y = j + dy;
                    if (0 <= x && x < m && 0 <= y && y < n && !on_fire[x][y] && grid[x][y] == 0 && !vis[x][y]) {
                        if (x == m - 1 && y == n - 1) {
                            return true;
                        }
                        vis[x][y] = 1;
                        nq.emplace_back(x, y);
                    }
                }    
            }
            q = move(nq);
            spread_fire();
        }
        return false; 
    }

    int maximumMinutes(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        int left = 0, right = m * n;
        int res = -1;
        while (left <= right) {
            int mid = (left + right) >> 1;
            if (check(grid, mid)) {
                res = mid;
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        return res < m * n ? res : 1e9;
    }
};

复杂度分析

时间复杂度: O ( m n l o g m n ) O(mnlogmn) O(mnlogmn) m m m n n n 分别为 grid 的行数和列数,二分枚举 O ( l o g m n ) O(logmn) O(logmn) 次,每次 check() 的时间为 O ( m n ) O(mn) O(mn)

空间复杂度: O ( m n ) O(mn) O(mn)

写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年11月PHP测试覆盖率解决方案

【题记&#xff1a;最近进行了ExcelBDD PHP版的开发&#xff0c;查阅了大量资料&#xff0c;发现PHP测试覆盖率解决方案存在不同的历史版本&#xff0c;让我花费了蛮多时间&#xff0c;为了避免后人浪费时间&#xff0c;整理本文&#xff0c;而且网上没有给出Azure DevOps里面P…

GPT-4-Turbo的128K长度上下文性能如何?超过73K Tokens的数据支持依然不太好!

本文原文来自DataLearnerAI官方网站&#xff1a;GPT-4-Turbo的128K长度上下文性能如何&#xff1f;超过73K Tokens的数据支持依然不太好&#xff01; | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051699526438975 GPT-4 Turbo是OpenAI最新发布的号称…

MySQL:锁机制

目录 概述三种层级的锁锁相关的 SQLMyISAM引擎下的锁InnoDB引擎下的锁InnoDB下的表锁和行锁InnoDB下的共享锁和排他锁InnoDB下的意向锁InnoDB下的记录锁&#xff0c;间隙锁&#xff0c;临键锁记录锁&#xff08;Record Locks&#xff09;间隙锁&#xff08;Gap Locks&#xff0…

基于光流法的车辆检测计数算法matlab仿真,对比Horn-Schunck光流和Lucas-Kanade光流

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 Horn-Schunck光流法 4.2 Lucas-Kanade光流法 5.算法完整程序工程 1.算法运行效果图预览 HS光流 LK光流 2.算法运行软件版本 matlab2022a 3.部分核心程序 ........................…

nav2 调节纯追踪算法

纯追踪算法 纯追踪基础 The core idea is to find a point on the path in front of the robot and find the linear and angular velocity to help drive towards it. 核心思想是在机器人前方的路径上找到一个点&#xff0c;并找到一个合适的线速度和角速度&#xff0c;以驱…

Netty 是如何利用EventLoop实现千万级并发的

经过前面几篇文章的介绍&#xff0c;我们掌握了 Netty 的 5 个核心组件&#xff0c;但是有了这 5 个核心组件 Netty 这个工厂还是无法很好的运转&#xff0c;因为缺少了一个最核心的组件&#xff1a;EventLoop&#xff0c;它 是 Netty 中最最核心的组件&#xff0c;也是 Netty …

竞赛选题 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习疫情社交安全距离检测算法 ** 该项目较为新颖&#xff0c;适合作为竞赛…

SQL 注入漏洞详解

SQL 注入漏洞详解 漏洞描述 sql注入漏洞是指恶意用户在应用与数据库交互的地方利用非法的操作获取数据库内容从以下两点分析: 没有对用户输入的数据进行充分的过滤和验证&#xff0c;导致一些用户利用此漏洞向数据库插入恶意sql语句非法请求数据库从而获得一些敏感数据在与数…

【服务发现与配置】Consul特性及搭建

文章目录 一、前言二、概念2.1、什么是Consul&#xff1f;2.2、Consul具有哪些特点?2.3、Consul 架构图2.4、Consul的使用场景 三、安装3.1. 下载3.2. 解压3.3. 拷贝到usr目录下3.4. 查看 安装是否成功3.5. 启动 四、Consul 开机自启动4.1. 路径/usr/lib/systemd/system/&…

ubuntu 安装redis详细教程

下载redis安装包 链接如下&#xff1a; http://redis.io/download 本例版本为&#xff1a;redis-7.2.3.tar.gz 下载安装包到目录/opt下&#xff0c;路径可修改&#xff0c;本例为/opt wget https://github.com/redis/redis/archive/7.2.3.tar.gz 解压安装包&#xff0c;并…

操作系统 day09(线程)

线程 为什么引入线程 在没引入进程之前&#xff0c;系统中的各个程序只能串行的执行&#xff0c;比如&#xff1a;只能先听歌&#xff0c;再聊QQ。引入进程之后&#xff0c;各个程序可以并发执行&#xff0c;比如&#xff1a;一边听歌&#xff0c;一边聊QQ。但是现在QQ可以一…

C++ 图解二叉树非递归中序 + 实战力扣题

leetCode 94.二叉树的中序遍历 94. 二叉树的中序遍历 - 力扣&#xff08;LeetCode&#xff09; 算法思路&#xff1a; 总结&#xff1a; 对中序遍历这个例子进行总结&#xff0c;找出打印“中”节点的时刻&#xff0c;来寻找本质。打印的是一棵二叉树的“中”节点&#xff0c…

MySQL -- mysql connect

MySQL – mysql connect 文章目录 MySQL -- mysql connect一、Connector/C 使用1.环境安装2.尝试链接mysql client 二、MySQL接口1.初始化2.链接数据库3.下发mysql命令4.获取执行结果5.关闭mysql链接6.在C语言中连接MySQL 三、MySQL图形化界面推荐 使用C接口库来进行连接 一、…

Python按类别和比例从Labelme数据集中划分出训练数据集和测试数据集

Python按类别和比例从Labelme数据集中划分出训练数据集和测试数据集 前言前提条件相关介绍实验环境按类别和比例从Labelme数据集中划分出训练数据集和测试数据集代码实现输出结果 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#x…

Java算法(六):模拟评委打分案例 方法封装抽离实现 程序的节流处理

Java算法&#xff08;六&#xff09; 评委打分 需求&#xff1a; 在编程竞赛中&#xff0c;有 6 个评委为参赛选手打分&#xff0c;分数为 0 - 100 的整数分。 选手的最后得分为&#xff1a;去掉一个最高分和一个最低分后 的 4个评委的平均值。 注意程序的节流 package c…

聊聊室内导航在应用方面

大家去大型的商场时&#xff0c;应该都见过一些提示牌&#xff0c;微信扫一扫导航。当拿微信扫了之后&#xff0c;就会打开一个小程序&#xff0c;里面显示整个商场的二维或三维的平面结构&#xff0c;以及当前自己的位置。此时可以通过手机快速的查看商场内其他的商铺、公共区…

NAND Vpass对读干扰和IO性能有什么影响?

1.SSD基础知识 SSD的存储介质是什么&#xff0c;它就是NAND闪存。那你知道NAND闪存是怎么工作的吗&#xff1f;其实&#xff0c;它就是由很多个晶体管组成的。这些晶体管里面存储着电荷&#xff0c;代表着我们的二进制数据&#xff0c;要么是“0”&#xff0c;要么是“1”。NA…

C++打怪升级(十)- STL之vector

~~~~ 前言1. vector 是什么2. 见见vector的常用接口函数吧构造函数无参构造函数使用n个val构造拷贝构造使用迭代器范围构造初始化形参列表构造 析构函数赋值运算符重载函数元素访问[]运算符重载函数访问at函数访问front函数back函数 迭代器相关正向迭代器反向迭代器 容量相关si…

2023.11.09 homework (2)

【七年级上数学】 教别人也是教自己&#xff0c;总结下&#xff1a; 13&#xff09;找规律的题目&#xff0c;累加题目&#xff0c;要整体看&#xff0c;不然不容易算出来&#xff0c;求最大值&#xff0c;那么就是【最大值集群和】减去【最小集群和】就是最大值 9-12&#x…

Python进行数据可视化,探索和发现数据中的模式和趋势。

文章目录 前言第一步&#xff1a;导入必要的库第二步&#xff1a;加载数据第三步&#xff1a;创建基本图表第四步&#xff1a;添加更多细节第五步&#xff1a;使用Seaborn库创建更复杂的图表关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Pyth…