【C++BFS】959. 由斜杠划分区域

本文涉及知识点

C++BFS算法

LeetCode959. 由斜杠划分区域

在由 1 x 1 方格组成的 n x n 网格 grid 中,每个 1 x 1 方块由 ‘/’、‘’ 或空格构成。这些字符会将方块划分为一些共边的区域。
给定网格 grid 表示为一个字符串数组,返回 区域的数量 。
请注意,反斜杠字符是转义的,因此 ‘’ 用 ‘\’ 表示。
示例 1:
在这里插入图片描述

输入:grid = [" /“,”/ "]
输出:2
示例 2:

在这里插入图片描述

输入:grid = [" /“,” "]
输出:1
示例 3:

输入:grid = [“/\”,“\/”]
输出:5
解释:回想一下,因为 \ 字符是转义的,所以 “/\” 表示 /\,而 “\/” 表示 /。

提示:
n == grid.length == grid[i].length
1 <= n <= 30
grid[i][j] 是 ‘/’、‘’、或 ’ ’

题解

任意单格内部分四块,上下左右单格内编号分别为0,1,2,3。
在这里插入图片描述

如果此单格是空格,则0,1,2,3相连。
如果此空格是斜杠,则0,2 相连,1,3向量。
如果是反斜杠,则0,3相连,1,2相连。
各的编号:4*(r*n+c)+单格内编号。
可以直接用并集查找(并查集)计算连通区域,本文用BFS。

C++BFS

编号从小到大枚举各块,如果不属于任意区域,则将此块及相连的区域划分到cnt区域,并cnt++。
region[i]记录第i块,在那个区域,默认值-1,表示不属于任何区域。
neiBo是各块的邻接表。
BFS的状态表示:leves[i]记录和root通过i条边相连的块。
BFS的后续状态:通过next枚举neiBo[cur]
BFS的初始值:leves[0]={root}
BFS的返回值:无。
BFS的重复处理:利用region出重。
必须判断上一行是否存在,不能只判断编号是否n合法:
n=2时,块10的左边不存在,如果不判断c>0,则块10和块7连通。

代码

核心代码

class Solution {
		public:
			int regionsBySlashes(vector<string>& grid) {
				const int N = grid.size();
				const int N1 = N * N * 4;
				vector<vector<int>> vNeiBo(N1);
				auto Add = [&vNeiBo,&N1](int n1, int n2) {
					if ((n1 < 0) || (n1 >= N1)) { return; }
					if ((n2 < 0) || (n2 >= N1)) { return; }
					vNeiBo[n1].emplace_back(n2);
					vNeiBo[n2].emplace_back(n1);
				};
				//单格内部连接
				for (int r = 0; r < N; r++) {
					for (int c = 0; c < N; c++) {
						const int iBase = 4 * (N * r + c);
						if ('\\' != grid[r][c]) {
							Add(iBase, iBase + 2);
							Add(iBase+1, iBase + 3);
						}
						if ('/' != grid[r][c]) {
							Add(iBase, iBase + 3);
							Add(iBase + 1, iBase + 2);
						}
					}
				}
				//单格间连接
				for (int r = 0; r < N; r++) {
					for (int c = 0; c < N; c++) {
#define Mask(r,c,n) ((N*(r)+(c))*4+(n))
						if (r > 0)
						{
							Add(Mask(r, c, 0), Mask(r - 1, c, 1));//本行上 上一行下
						}
						if (r + 1 < N)
						{
							Add(Mask(r, c, 1), Mask(r + 1, c, 0));//本行下 下一行上
						}
						if (c > 0)
						{
							Add(Mask(r, c, 2), Mask(r, c - 1, 3));//本行左 左列右
						}
						if (c + 1 < N)
						{
							Add(Mask(r, c, 3), Mask(r, c + 1, 2));//本行右 右列左
						}
					}
				}

				vector<int> region(N1, -1);
				int cnt = 0;
				for (int i = 0; i < N1; i++) {
					if (-1 != region[i]) { continue; }
					queue<int> que;
					que.emplace(i);
					region[i] = cnt;
					while (que.size()) {
						auto cur = que.front();
						que.pop();
						for (const auto& next : vNeiBo[cur]) {
							if (-1 != region[next]) { continue; }
							region[next] = cnt;
							que.emplace(next);
						}
					}
					cnt++;
				}
				return cnt;
			}
		};

单元测试

vector<string> grid;
		TEST_METHOD(TestMethod1)
		{
			grid = { " " };
			auto res = Solution().regionsBySlashes(grid);
			AssertEx(1, res);
		}
		TEST_METHOD(TestMethod2)
		{
			grid = { "/" };
			auto res = Solution().regionsBySlashes(grid);
			AssertEx(2, res);
		}
		TEST_METHOD(TestMethod3)
		{
			grid = { "\\" };
			auto res = Solution().regionsBySlashes(grid);
			AssertEx(2, res);
		}
		TEST_METHOD(TestMethod11)
		{
			grid = { " /","/ " };
			auto res = Solution().regionsBySlashes(grid);
			AssertEx(2, res);
		}
		TEST_METHOD(TestMethod12)
		{
			grid = { " /","  " };
			auto res = Solution().regionsBySlashes(grid);
			AssertEx(1, res);
		}
		TEST_METHOD(TestMethod13)
		{
			grid = { "/\\","\\/" };
			auto res = Solution().regionsBySlashes(grid);
			AssertEx(5, res);
		}

扩展阅读

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

视频课程

先学简单的课程,请移步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++**实现。

  • 13
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
好的,以下是一个基于C++BFS求最短路径的示例代码: ```cpp #include <iostream> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; // 最大节点数 const int INF = 0x3f3f3f3f; // 无穷大 int n, m; // n表示节点个数,m表示边数 int dis[MAXN]; // 存储起点到每个节点的距离 bool vis[MAXN]; // 记录每个节点是否被访问过 int head[MAXN], to[MAXN<<1], nxt[MAXN<<1], edge[MAXN<<1], cnt; // 邻接表存图 void addEdge(int u, int v, int w) { to[++cnt] = v; nxt[cnt] = head[u]; edge[cnt] = w; head[u] = cnt; } void bfs(int start) { memset(dis, INF, sizeof(dis)); // 初始化距离为无穷大 memset(vis, false, sizeof(vis)); // 初始化所有节点都未被访问过 dis[start] = 0; // 起点到自己的距离为0 vis[start] = true; // 起点已经访问过了 queue<int> q; // 定义一个队列,用于广度优先搜索 q.push(start); // 将起点加入队列 while (!q.empty()) { int u = q.front(); q.pop(); // 取出队首节点 for (int i = head[u]; i; i = nxt[i]) { int v = to[i], w = edge[i]; if (!vis[v]) { // 如果这个节点未被访问过 dis[v] = dis[u] + w; // 更新距离 vis[v] = true; // 标记为已访问 q.push(v); // 将其加入队列 } } } } int main() { cin >> n >> m; for (int i = 1; i <= m; ++i) { int u, v, w; cin >> u >> v >> w; addEdge(u, v, w); addEdge(v, u, w); // 无向图需要加两条边 } int start; cin >> start; bfs(start); for (int i = 1; i <= n; ++i) { if (dis[i] != INF) { cout << start << " 到 " << i << " 的最短距离为:" << dis[i] << endl; } } return 0; } ``` 这段代码使用邻接表存图,时间复杂度为O(n+m),其中n表示节点数,m表示边数。在实际使用中,可以根据自己的需求进行修改。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闻缺陷则喜何志丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值