iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++回溯算法广度优先搜索举例分析
  • 395
分享到

C++回溯算法广度优先搜索举例分析

2024-04-02 19:04:59 395人浏览 八月长安
摘要

目录迷宫问题N叉树的层序遍历腐烂的橘子单词接龙打开转盘锁迷宫问题 假设有一个迷宫,里面有障碍物,迷宫用二维矩阵表示,标记为0的地方表示可以通过,标记为1的地方表示障碍物,不能通过。现

迷宫问题

假设有一个迷宫,里面有障碍物,迷宫用二维矩阵表示,标记为0的地方表示可以通过,标记为1的地方表示障碍物,不能通过。现在给一个迷宫出口,让你判断是否可以从入口进来之后,走出迷宫,每次可以向任意方向走。

代码实现:


namespace BFS {
	struct pair {
		int _x;
		int _y;

		pair(int x, int y)
			:_x(x)
			, _y(y)
		{}
	};

	bool mapBFS(vector<vector<int>> mat, int sx, int sy, int ex, int ey)
	{
		int row = mat.size();
		int col = mat[0].size();

		queue<pair> q;
		q.push(pair(sx, sy));
		vector<vector<int>> book(row, vector<int>(col, 0));
		book[sx][sy] = 1;

		int nextP[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

		while (!q.empty())
		{
			pair curPos = q.front();
			q.pop();
			if (curPos._x == ex && curPos._y == ey)
				return true;
			//一个点的所有可能延伸的点
			for (int i = 0; i < 4; i++)
			{
				int curX = curPos._x + nextP[i][0];
				int curY = curPos._y + nextP[i][1];

				if (curX < 0 || curX >= row || curY < 0 || curY >= col)
					continue;
				//没有走过且不是障碍物
				if (mat[curX][curY] == 0 && book[curX][curY] == 0)
				{
					book[curX][curY] = 1;
					//保存新的位置
					q.push(pair(curX, curY));
				}
			}
		}

		return false;
	}
}

int main()
{
	vector<vector<int>> mat{ {0, 0, 1, 0},
							 {1, 0, 0, 1},
							 {0, 0, 0, 0},
							 {1, 1, 0, 0} };
	int sx, sy, ex, ey;
	cin >> sx >> sy >> ex >> ey;
	cout << BFS::mapBFS(mat, sx, sy, ex, ey);

	return 0;
}

N叉树的层序遍历

问题描述:

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。 树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

代码实现:




class Solution {
public:
    vector<vector<int>> levelOrder(node* root) {
        vector<vector<int>> result;
        if(!root)
            return result;
        queue<Node*> q;
        q.push(root);
        while(!q.empty())
        {
            //获取队列中的元素个数
            int sz = q.size();
            vector<int> rowV;
            while(sz--)
            {
                //保存当前元素在同一行
                Node* node = q.front();
                q.pop();
                rowV.push_back(node->val);
                //当前元素的孩子结点入队
                for(auto e : node->children)
                {
                    q.push(e);
                }
            }
            result.push_back(rowV);
        }

        return result;
    }
};

腐烂的橘子

问题描述:

在给定的网格中,每个单元格可以有以下三个值之一:

值 0 代表空单元格;

值 1 代表新鲜橘子;

值 2 代表腐烂的橘子。

每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。

本题可以先找到所有的腐烂橘子入队,用第一批带出新一批腐烂的橘子。 每一批橘子都会在一分钟之内腐烂,所以此题可以转化为求BFS执行的大循环的次数。这里的step的更新需要有一个标记,只有新的腐烂的橘子加入,step才++ 最后BFS执行完,说明所有可以被腐烂的都完成了,再去遍历grid,如果还有值为1的,说明没有办法全部腐烂,返回-1,如果没有,则返回step

代码实现:


class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int step = 0;
        int row = grid.size();
        int col = grid[0].size();
        queue<pair<int, int>> q;
        //把所有腐烂的橘子入队
        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 2)
                    q.push(make_pair(i, j));
            }
        }

        static int nextP[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0 ,1}};
        while(!q.empty()){
            int sz = q.size();
            bool flag = false;
            while(sz--){
                pair curPos = q.front();
                q.pop();
                for(int i = 0; i < 4; i++){
                    int curX = curPos.first + nextP[i][0];
                    int curY = curPos.second + nextP[i][1];
                    if(curX < 0 || curX >= row || curY < 0 || curY >= col)
                        continue;
                    if(grid[curX][curY] == 1){
                        flag = true;
                        grid[curX][curY] = 2;
                        q.push(make_pair(curX, curY));
                    }
                }
            }
            if(flag)
                ++step;
        }

        for(int i = 0; i < row; i++){
            for(int j = 0; j < col; j++){
                if(grid[i][j] == 1)
                    return -1;
            }
        }

        return step;
    }
};

单词接龙

问题描述:

字典 WordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:

序列中第一个单词是 beginWord 。

序列中最后一个单词是 endWord 。

每次转换只能改变一个字母。

转换过程中的中间单词必须是字典 wordList 中的单词。

给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。

示例 1:

输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]

输出:5

解释:一个最短转换序列是 “hit” -> “hot” -> “dot” -> “dog” -> “cog”, 返回它的长度 5。

1.通过BFS,首先用beginWord带出转换一个字符之后所有可能的结果

2.每一步都要把队列中上一步添加的所有单词转换一遍,最短的转换肯定在这些单词中,所有这些词的转换只能算一次转换,因为都是上一步转换出来的,这里对于每个单词的每个位置都可以用26个字母进行转换,所以一个单词一次转换的可能有:单词的长度*25

3.把转换成功的新词入队,进行下一步的转换

4.最后整个转换的长度就和BFS执行的次数相同

需要判断单词有没有被搜索过,是一个查询的过程,可以用哈希表

代码实现:


class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        int step = 1;
        unordered_set<string> book;
        unordered_set<string> dict;
        book.insert(beginWord);
        for(string& ch : wordList)
            dict.insert(ch);
        queue<string> q;
        q.push(beginWord);

        while(!q.empty()){
            int size = q.size();
            while(size--){
                string curStr = q.front();
                q.pop();
                if(curStr == endWord)
                    return step;
                for(int i = 0; i < curStr.size(); i++){
                    string str1 = curStr;
                    for(char ch = 'a'; ch <= 'z'; ++ch){
                        str1[i] = ch;
                        //判断新的单词是否在词典中,且没被搜索过
                        if(dict.find(str1) != dict.end()
                        && book.find(str1) == book.end()){
                            q.push(str1);
                            book.insert(str1);
                        }
                    }
                }
            }
            ++step;
        }
        
        return 0;
    }
};

打开转盘锁

问题描述:

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0', ‘1', ‘2', ‘3', ‘4', ‘5', ‘6', ‘7', ‘8', ‘9' 。每个拨轮可以自由旋转:例如把 ‘9' 变为 ‘0',‘0' 变为 ‘9' 。每次旋转都只能旋转一个拨轮的一位数字。

锁的初始数字为 ‘0000' ,一个代表四个拨轮的数字的字符串

列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。

深度优先不适合此题,递归深度太大,会导致栈溢出。

本题的密码为4位密码,每位密码可以通过拨动一次进行改变,注意这里的数的回环以及拨动的方向拨动方向:向前,向后。

回环:如果当前是9,0时,向前,向后拨动需要变成最小最大,而不是简单的自加自减。

0000一步旋转后的结果有:

0001 0009 0010 0090 0100 0900 1000 9000

代码实现:


class Solution {
public:
    int openLock(vector<string>& deadends, string target) {
        unordered_set<string> deaddict(deadends.begin(), deadends.end());
        //如果0000在死亡数字中,则永远也到不了
        if(deaddict.find("0000") != deaddict.end())
            return -1;
        queue<string> q;
        q.push("0000");
        //添加标记,已经搜索过的字符不再搜索
        unordered_set<string> book;
        book.insert("0000");
        int step = 0;
        while(!q.empty()){
            int size = q.size();
            while(size--){
                string curStr = q.front();
                q.pop();
                if(curStr == target)
                    return step;
                for(int i = 0; i < 4; i++){
                    string s1 = curStr;
                    string s2 = curStr;
                    //向前或向后旋转
                    s1[i] = s1[i] =='0' ? '9' : --s1[i];
                    s2[i] = s2[i] =='9' ? '0' : ++s2[i];
                    if(deaddict.find(s1) == deaddict.end()
                    && book.find(s1) == book.end()){
                        q.push(s1);
                        book.insert(s1);
                    }
                    if(deaddict.find(s2) == deaddict.end()
                    && book.find(s2) == book.end()){
                        q.push(s2);
                        book.insert(s2);
                    }
                }
            }
            ++step;
        }

        return -1;
    }
};

到此这篇关于c++回溯算法广度优先搜索举例分析的文章就介绍到这了,更多相关C++ 回溯算法 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++回溯算法广度优先搜索举例分析

本文链接: https://www.lsjlt.com/news/143803.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++回溯算法广度优先搜索举例分析
    目录迷宫问题N叉树的层序遍历腐烂的橘子单词接龙打开转盘锁迷宫问题 假设有一个迷宫,里面有障碍物,迷宫用二维矩阵表示,标记为0的地方表示可以通过,标记为1的地方表示障碍物,不能通过。现...
    99+
    2024-04-02
  • C++回溯算法深度优先搜索举例分析
    目录扑克牌全排列员工的重要性图像渲染被围绕的区域岛屿数量电话号码的字母组合组合总数活字印书N皇后扑克牌全排列 假如有编号为1~ 3的3张扑克牌和编号为1~3的3个盒子,现在需要将3张...
    99+
    2024-04-02
  • C++回溯算法深度优先搜索的示例分析
    小编给大家分享一下C++回溯算法深度优先搜索的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!扑克牌全排列假如有编号为1~ 3的3张扑克牌和编号为1~3的3个盒子,现在需要将3张牌分别放到3个盒子中去,且每个盒子只能...
    99+
    2023-06-29
  • LeetCode中广度优先搜索算法的示例分析
    小编给大家分享一下LeetCode中广度优先搜索算法的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、认识广度优先搜索算法广度优先搜索(BFS)算法是图...
    99+
    2023-06-19
  • C++回溯算法之深度优先搜索详细介绍
    目录一、前言二、基本概念1.简单介绍2. 官方概念三、动图分析四、模板框架五、例题分析组合问题题干描述思路分析一、前言 本文介绍了经典搜索算法: 深度优先搜索(DFS) 两个小故事:...
    99+
    2023-01-13
    C++深度优先搜索 C++深度优先搜索算法
  • Java实现深度优先搜索(DFS)和广度优先搜索(BFS)算法
    目录一.深度优先遍历和广度优先遍历1.深度优先遍历2.广度优先遍历二.图像渲染1.题目描述2.问题分析3代码实现1.广度优先遍历2.深度优先遍历三.岛屿的最大面积1.题目描述2.问题...
    99+
    2023-05-18
    Java深度优先和广度优先 Java深度优先 Java广度优先
  • Python 算法基础篇:深度优先搜索( DFS )和广度优先搜索( BFS )
    Python 算法基础篇:深度优先搜索( DFS )和广度优先搜索( BFS ) 引言 1. 深度优先搜索( DFS )算法概述2. 深度优先搜索( DFS )算法实现实例1:图的 DFS 遍...
    99+
    2023-10-04
    深度优先 算法 python 广度优先
  • JavaScript中深度优先遍历和广度优先遍历算法的示例分析
    这篇文章主要为大家展示了“JavaScript中深度优先遍历和广度优先遍历算法的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript中深度...
    99+
    2024-04-02
  • Python实现图的广度和深度优先路径搜索算法
    目录前言1. 图理论1.1 图的概念1.2 定义图1.3 图的抽象数据结构2. 图的存储实现2.1 邻接矩阵2.2 编码实现邻接矩阵3. 搜索路径3.1 广度优先搜索3.2 深度优先...
    99+
    2024-04-02
  • Java中深度优先与广度优先的示例分析
    这篇文章给大家分享的是有关Java中深度优先与广度优先的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开发...
    99+
    2023-05-30
    java
  • C语言中深度优先搜索(DFS)算法的示例详解
    目录迷宫问题思路实现代码深搜的剪枝优化可行性剪枝最优性剪枝迷宫问题 有一个迷宫: S**.....***T (其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地。你需...
    99+
    2023-02-16
    C语言深度优先搜索算法 C语言 DFS算法
  • Python怎么实现图的广度和深度优先路径搜索算法
    本篇内容主要讲解“Python怎么实现图的广度和深度优先路径搜索算法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python怎么实现图的广度和深度优先路径搜索算法”吧!前言图是一种抽象数据结构...
    99+
    2023-06-30
  • java迷宫算法的理解(递归分割,递归回溯,深搜,广搜)
    目录递归分割法:递归回溯法:广度优先深度优先:下面是递归分割法、递归回溯法以及文件加载地图实现的类map最近这学期做了一个java迷宫的课程设计,这里代码及其算法逻辑就分享出来。 首...
    99+
    2024-04-02
  • JavaScript树结构深度优先算法实例分析
    这篇文章主要介绍了JavaScript树结构深度优先算法实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript树结构深度优先算法实例分析文章都会有所收获,下面我们一起来看看吧。什么是树在现实...
    99+
    2023-07-02
  • C语言算法举例分析
    这篇文章主要介绍“C语言算法举例分析”,在日常操作中,相信很多人在C语言算法举例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言算法举例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!最近,我一...
    99+
    2023-06-17
  • C#的运算符优先级实例分析
    这篇文章主要介绍了C#的运算符优先级实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#的运算符优先级实例分析文章都会有所收获,下面我们一起来看看吧。实例using System;namespa...
    99+
    2023-06-17
  • C++回溯算法中子集问题分析探讨
    目录一、子集二、子集II三、递增子序列 一、子集 子集问题与其它问题最大的不同就是:每次递归,不止考虑叶子节点,而是考虑所有节点! 体现在代码上,就是每次递归都先result.pus...
    99+
    2023-03-15
    C++回溯算法子集 C++回溯算法 C++子集问题
  • Java分治法与二分搜索算法实例分析
    本文实例讲述了Java分治法与二分搜索算法。分享给大家供大家参考,具体如下:1、分治法分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归的解这些子问题,然后将各子问题的解合并得到原问题的...
    99+
    2023-05-30
    java 分治法 二分搜索
  • C++回溯算法中组合的相关问题分析
    目录一、组合二、组合总和III与组合总和1.组合总和III2.组合总和3.组合总和II三、电话号码的字母组合 回溯算法模板 void backtracking(参数) { ...
    99+
    2023-03-15
    C++回溯算法组合 C++回溯算法
  • C++回溯算法中的全排列问题分析探讨
    目录一、全排列二、全排列II 一、全排列 全排列的特点就是:解放了index(每次遍历都从0开始),但是解放index的同时,又捆绑了used数组,记录已经出现过的元素 class ...
    99+
    2023-03-15
    C++回溯算法全排列 C++回溯算法 C++全排列问题
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作