【[C++BFS】1765. 地图中的最高点

news2024/12/24 21:01:03

本文涉及知识点

C++BFS算法

LeetCoce1765. 地图中的最高点

给你一个大小为 m x n 的整数矩阵 isWater ,它代表了一个由 陆地 和 水域 单元格组成的地图。
如果 isWater[i][j] == 0 ,格子 (i, j) 是一个 陆地 格子。
如果 isWater[i][j] == 1 ,格子 (i, j) 是一个 水域 格子。
你需要按照如下规则给每个单元格安排高度:
每个格子的高度都必须是非负的。
如果一个格子是 水域 ,那么它的高度必须为 0 。
任意相邻的格子高度差 至多 为 1 。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格子。(也就是说它们有一条公共边)
找到一种安排高度的方案,使得矩阵中的最高高度值 最大 。
请你返回一个大小为 m x n 的整数矩阵 height ,其中 height[i][j] 是格子 (i, j) 的高度。如果有多种解法,请返回 任意一个 。
示例 1:
在这里插入图片描述

输入:isWater = [[0,1],[0,0]]
输出:[[1,0],[2,1]]
解释:上图展示了给各个格子安排的高度。
蓝色格子是水域格,绿色格子是陆地格。
示例 2:
在这里插入图片描述

输入:isWater = [[0,0,1],[1,0,0],[0,0,0]]
输出:[[1,1,0],[0,1,1],[1,2,2]]
解释:所有安排方案中,最高可行高度为 2 。
任意安排方案中,只要最高高度为 2 且符合上述规则的,都为可行方案。

提示:
m == isWater.length
n == isWater[i].length
1 <= m, n <= 1000
isWater[i][j] 要么是 0 ,要么是 1 。
至少有 1 个水域格子。

C++BFS

BFS的预处理:陆地更改成-1,水域更改为0。
BFS的初始状态:leves[0] = {所有水域单格}。
BFS的状态表示:leves[i]记录任意水域的最近距离为i的陆地。
BFS的后续状态:通过next访问cur的四连通临接点。
BFS的返回值:grid。
BFS的重复处理:利用grid做重复处理。grid[r][c]为-1,表示未处理。

正确性证明

从小到处理leves[i]。
i为1是,因为和水域相邻,故最大为1。由于已处理的单格和当前单格相邻的一定是leves[0]和leves[1]故为1,不会冲同。
⋮ \vdots
leves[i]和leves[i-1]相邻,故最大为i。和已经处理单格相邻的只会是leves[i]和leves[i-1],故不会冲突。

代码

核心代码

class CGrid {
public:
	CGrid(int rCount, int cCount) :m_r(rCount), m_c(cCount) {}
	vector<vector<pair<int, int>>> NeiBo(std::function<bool(int, int)> funVilidCur, std::function<bool(int, int)> funVilidNext, int iConnect = 4)
	{
		vector<vector<pair<int, int>>> vNeiBo(m_r * m_c);
		auto Move = [&](int preR, int preC, int r, int c)
		{
			if ((r < 0) || (r >= m_r))
			{
				return;
			}
			if ((c < 0) || (c >= m_c))

			{
				return;
			}
			if (funVilidCur(preR, preC) && funVilidNext(r, c))
			{
				vNeiBo[Mask(preR, preC)].emplace_back(r, c);
			}
		};

		for (int r = 0; r < m_r; r++)
		{
			for (int c = 0; c < m_c; c++)
			{
				for (int k = 0; k < iConnect; k++)
				{
					Move(r, c, r + s_Moves[k][0], c + s_Moves[k][1]);
				}
			}
		}
		return vNeiBo;
	}
	 void EnumGrid(std::function<void(int, int)> call)
	{
		for (int r = 0; r < m_r; r++)
		{
			for (int c = 0; c < m_c; c++)
			{
				call(r, c);
			}
		}
	}
	inline int Mask(int r, int c) { return  m_c * r + c; }
	const int m_r, m_c;
	const inline static int s_Moves[][2] = { {1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1} };
};

class Solution {
		public:
			vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {
				queue<pair<int, int>> que;
				CGrid ng(isWater.size(), isWater[0].size());
				ng.EnumGrid([&](int r, int c) {
					if (1 == isWater[r][c]) {
						isWater[r][c] = 0;
						que.emplace(r, c);
					}
					else {
						isWater[r][c] = -1;
					}});
				auto neiBo = ng.NeiBo([](int r, int c) {return true; }, [&](int r, int c) {return 0 != isWater[r][c]; });				
				while (que.size()) {
					const auto [r, c] = que.front();
					que.pop();
					for (const auto& [r1, c1] : neiBo[ng.Mask(r, c)]) {
						if (-1 == isWater[r1][c1]) {
							isWater[r1][c1] = isWater[r][c] + 1;
							que.emplace(r1, c1);
						}
					}
				}
				return isWater;
			}
		};

单元测试

	vector<vector<int>> isWater;
		void Check(const vector<vector<int>>& res, const vector<vector<int>>& isWater,int iMax)
		{
			Assert::AreEqual((int)res.size(), (int)isWater.size());
			Assert::AreEqual((int)res[0].size(), (int)isWater[0].size());
			int iActMax = 0;
			for (int r = 0; r < res.size(); r++) {
				iActMax = max(iActMax, *std::max_element(res[r].begin(),res[r].end()));
				for (int c = 0; c < res[0].size(); c++) {
					if (0 == isWater[r][c]) {
						Assert::AreEqual(0, res[r][c]);						
					}
					if (r > 0) {
						Assert::IsTrue(abs(res[r][c] - res[r - 1][c]) <= 1);
					}
					if (c > 0) {
						Assert::IsTrue(abs(res[r][c] - res[r][c - 1]) <= 1);
					}
				}
			}		
		}
		TEST_METHOD(TestMethod1)
		{
			isWater = { {1} };
			auto res = Solution().highestPeak(isWater);
			Check(res, isWater,0);
		}
		TEST_METHOD(TestMethod2)
		{
			isWater = { {1,0,0,0,0} };
			auto res = Solution().highestPeak(isWater);
			Check(res, isWater, 4);
		}
		TEST_METHOD(TestMethod3)
		{
			isWater = { {1,0,0,0,1} };
			auto res = Solution().highestPeak(isWater);
			Check(res, isWater, 2);
		}
		TEST_METHOD(TestMethod11)
		{
			isWater = { {0,1},{0,0} };
			auto res = Solution().highestPeak(isWater);
			Check(res, isWater,2);
		}
		TEST_METHOD(TestMethod12)
		{
			isWater = { {0,0,1},{1,0,0},{0,0,0} };
			auto res = Solution().highestPeak(isWater);
			Check(res, isWater,2);
		}

使用模板代码

class CGrid {
public:
	CGrid(int rCount, int cCount) :m_r(rCount), m_c(cCount) {}
	vector<vector<pair<int, int>>> NeiBo(std::function<bool(int, int)> funVilidCur, std::function<bool(int, int)> funVilidNext, int iConnect = 4)
	{
		vector<vector<pair<int, int>>> vNeiBo(m_r * m_c);
		auto Move = [&](int preR, int preC, int r, int c)
		{
			if ((r < 0) || (r >= m_r))
			{
				return;
			}
			if ((c < 0) || (c >= m_c))

			{
				return;
			}
			if (funVilidCur(preR, preC) && funVilidNext(r, c))
			{
				vNeiBo[Mask(preR, preC)].emplace_back(r, c);
			}
		};

		for (int r = 0; r < m_r; r++)
		{
			for (int c = 0; c < m_c; c++)
			{
				for (int k = 0; k < iConnect; k++)
				{
					Move(r, c, r + s_Moves[k][0], c + s_Moves[k][1]);
				}
			}
		}
		return vNeiBo;
	}
	 void EnumGrid(std::function<void(int, int)> call)
	{
		for (int r = 0; r < m_r; r++)
		{
			for (int c = 0; c < m_c; c++)
			{
				call(r, c);
			}
		}
	}
	inline int Mask(int r, int c) { return  m_c * r + c; }
	const int m_r, m_c;
	const inline static int s_Moves[][2] = { {1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1} };
};

class Solution {
		public:
			vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {
				queue<pair<int, int>> que;
				CGrid ng(isWater.size(), isWater[0].size());
				ng.EnumGrid([&](int r, int c) {
					if (1 == isWater[r][c]) {
						isWater[r][c] = 0;
						que.emplace(r, c);
					}
					else {
						isWater[r][c] = -1;
					}});
				auto neiBo = ng.NeiBo([](int r, int c) {return true; }, [&](int r, int c) {return 0 != isWater[r][c]; });				
				while (que.size()) {
					const auto [r, c] = que.front();
					que.pop();
					for (const auto& [r1, c1] : neiBo[ng.Mask(r, c)]) {
						if (-1 == isWater[r1][c1]) {
							isWater[r1][c1] = isWater[r][c] + 1;
							que.emplace(r1, c1);
						}
					}
				}
				return isWater;
			}
		};

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

halcon深度学习语义分割预处理图片遇到的坑

1.最近使用halcon深度学习语义分割&#xff0c;做缺陷检测。 2.在使用halcon的深度学习标准工具&#xff0c;标注图片 3.标注好图片后&#xff0c;到处预处理&#xff0c;发现报错&#xff0c;[‘Multiple matching segmentation files for image /1.jpg’]意思是:[’ image /…

程序设计基础(c语言)

1、求n个数的平均数 float aver(float b[],int n) {int i;float ave0;for(i0;i<n;i){aveb[i];}ave/n; return ave; } 运行结果如下 2、本题要求实现一个函数&#xff0c;可求两个数的最大公约数&#xff0c;例如&#xff0c;12和8的最大公约数为4&#xff0c;则该函数应该…

打卡第31天------贪心算法

每天抓紧时间刷题,争取尽快上岸,不能再耽误一分一秒了,2024年已经过去大半年了。这个算法编程题是我的痛点。要尽快弥补。 卡尔在讲算法题的时候,思路比较清晰,通俗易懂,以前看见算法题就害怕,因为啥都不会,看懵了,跟了一个月了,每天坚持刷题,偶尔会回顾思路,也会…

计算机网络-PIM协议基础概念

一、PIM基础概念 组播网络回顾&#xff1a; 组播网络从网络结构上大体可以分为三个部分&#xff1a; 源端网络&#xff1a;将组播源产生的组播数据发送至组播网络。 组播转发网络&#xff1a;形成无环的组播转发路径&#xff0c;该转发路径也被称为组播分发树&#xff08;Multi…

Shell编程基本介绍

文章目录 Shell简介Shell环境第一个Shell脚本Shell脚本的运行方法 基础语法Shell变量定义变量使用变量修改变量的值单引号和双引号的区别将命令的结果赋值给变量只读变量删除变量 Shell传递参数特殊字符处理参数说明$* 与 $ 区别 Shell字符串三种形式的区别获取字符串长度Shell…

ajax图书管理项目

bootstrap弹框 不离开当前页面&#xff0c;显示单独内容&#xff0c;让用户操作 功能&#xff1a;不离开当前页面&#xff0c;显示单独内容&#xff0c;供用户操作步骤&#xff1a; 1.引入bootstrap.css和bootstrap.js …

Java关键字及保留字总结

文章目录 Java关键字及保留字总结&#xff08;按首字母字母顺序所排列&#xff09;1.abstract2.boolean3.break4.byte5.case6.catch7.char8.class9.continue10.default11.do12.double13.else14.enum15.extends16.final17.finally18.float19.for20.if21.implements22.import23.i…

delphi 12 学习如何登陆网站下载文件

启动时等待验证码. 输入验证码后,等待处理数据 处理完成后,显示数据 实现原理:利用已有的账号和密码登录后产生的cookie,向服务器请求数据.返回的数据是JSON格式,后期需要自己整理. 注意,请在程序中使用同一个TnetHttpClient控件来完成.因为里面保存了cookie信息 需要了解的知…

C#编写软件发布公告1——客户端

前言 软件或者生活中有时需要将信息同步至电子公告板上&#xff0c;利用C#可以快速实现这一目的&#xff0c;这里以软件公告场景设计&#xff0c;主要是将软件的版本号等相关信息同步至服务器&#xff0c;同步成功后&#xff0c;任务需要查找的人员只要有Web浏览器就可以快速查…

用前所未有的方式体验我们的现代 API 文档

增强您的 API 文档 对于开发人员 为内部和外部消费者创建从 API 定义文件自动生成的精美 API 文档。 只需 4 个简单步骤即可编写 API 文档 API 采用的成功取决于 API 文档的质量。 Baklib 从您的 API 定义文件创建漂亮的&#xff08;完全可定制的&#xff09;API 文档。帮助…

4个自定义倒计时

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><title>4个自定义倒计时</title><style>* {margin: 0;padding: 0;box-sizing: border-box;user-select: none;body {background: #0b1b2c;}}hea…

DedeCms 织梦系统 漏洞 上传webshell复现 四种方法 超详细

DedeCMS是织梦团队开发PHP 网站管理系统&#xff0c;它以简单、易用、高效为特色&#xff0c;组建出各种各样各具特色的网站&#xff0c;如地方门户、行业门户、政府及企事业站点等。 目录 方法一 &#xff1a;通过⽂件管理器上传WebShell 方法二&#xff1a;修改模板⽂件拿…

邻接矩阵实现图的存储

目录 一. 前言 二. 用邻接矩阵来实现图的存储 一. 前言 1. 图的定义 所谓图就是包含顶点和边的集合&#xff0c;是一种多对多的关系。用符号表示为&#xff1a;G(V,E)。其中&#xff0c;V代表顶点&#xff08;数据元素&#xff09;的有穷非空集合&#xff0c;E代表边的有穷集…

AI4-PPOCRLabel安装

推荐环境&#xff1a; - PaddlePaddle > 2.1.2 - Python 3.7 - CUDA10.1 / CUDA10.2 - CUDNN 7.6 1、安装Anaconda 说明&#xff1a;使用paddlepaddle需要先安装python环境&#xff0c;这里我们选择python集成环境Anaconda工具包 Anaconda是1个常用的python包管理程序 安装完…

虚拟机连接xshell的三种方式

第一 桥接 改为输入 systemctl restart network 关闭自启动防火墙 systemctl stop firewalld systemctl disable firewalld 查看本机网络信息 ifconfig 连接xshell 第二 nat 第三 仅主机

探索 Electron:打造深度书籍挖掘机的搜索体验

Electron是一个开源的桌面应用程序开发框架&#xff0c;它允许开发者使用Web技术&#xff08;如 HTML、CSS 和 JavaScript&#xff09;构建跨平台的桌面应用程序&#xff0c;它的出现极大地简化了桌面应用程序的开发流程&#xff0c;让更多的开发者能够利用已有的 Web 开发技能…

react-native从入门到实战系列教程-React Native Elements

react-native的ui框架内网真的是屈指可数&#xff0c;能用的成熟的几乎找不到。不像web端的繁荣景象&#xff0c;可以用荒凉来形容不为过。 京东的nutui说也支持react-native,官网及其简陋。尝试了未成功运行&#xff0c;可能是项目类型不同&#xff0c;对比其他类型的ui库都分…

centos安装es、kibana、ik

这里es使用的是7.10.2版本的es&#xff0c;物料包下载地址如下 #注意安装的插件需和es版本保持一致 #es https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.2-linux-x86_64.tar.gz #kibana https://artifacts.elastic.co/downloads/kibana/kibana-7.10…

phpMyAdmin之CMS靶场

方法一&#xff1a;通过日志文件拿webshell 常用的语句如下&#xff1a; show global variables like %general%; set global general_logon; set global general_log_file D:/phpStudy_pro/WWW/muma.php; show global variables like %general%; select <?php eval($_…

广西南宁高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

南宁高校大学智能制造实验室&#xff0c;作为该地区乃至全国智能制造领域的重要研究和教学基地&#xff0c;一直致力于探索和创新智能制造技术。近日&#xff0c;该实验室的数字孪生可视化系统平台建设项目成功通过了验收&#xff0c;标志着其在数字孪生技术领域取得了重大突破…