.BFS.

news2024/10/6 22:23:40

BFS

(Breadth-First Search)是一种用于遍历或搜索树(tree)或图(graph)的算法。
这个算法从根(或某个任意节点)开始,并探索最近的邻居节点,
然后再探索那些节点的邻居节点,如此类推,直到找到目标或已经探索了所有可达的节点。
BFS 是一种广度优先的搜索策略,也就是说,它首先访问所有相邻的节点,然后才访问下一层的节点。

BFS:可以搜到最短路径,是一圈一圈的进行搜索。所以题目若要求最短路问题,一定是BFS而非DFS。

题目:

AcWing 844. 走迷宫 - AcWing

 

思路:

第几层被扩展到,即距离原点多远:

当前所在的节点有四种可能性:向上(-1,0)、下(1,0)、左(0,-1)、右(0,1)扩展(这里的扩展时对应的是矩阵),我们分别枚举即可。

这里用两个一维数组来简化代码:dx[4]={-1,0,1,0},dy[4]={0,1,0,-1}

不可扩展的情况有1、扩展时下一节点数值为1,2、扩展时下一节点之前已经被其他路径扩展了(因为是要求最优解,之前被走过的路重复走会增加次数)3、扩展到边界了。

代码:

①:数组模拟队列

#include<iostream>
#include<algorithm>
#include<cstring>

const int N=105;
using namespace std;

int n,m;
//g数组存的是地图
int g[N][N];
//d数组存的是地图上的每一个点到起点的距离
int d[N][N];

//定义一个数组q[N],用来存放点的坐标
pair<int,int> q[N*N];

int bfs()
{
    //一开始队列为空
    int hh=0,tt=0;
    //起点坐标为(0,0)
    q[0]={0,0};
    //先将所有数组d[][]的值初始化为-1,-1表示没走过
    memset(d,-1,sizeof d);
    //一开始的起点已经走过了
    d[0][0]=0;
    //偏移量
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    
    while(hh <= tt)
    {
        /*
        每次取出队头(队头即为bfs宽搜时遇到的最新的一个点),
        然向上、下、左、右四个方向进行扩展
        */
        pair<int,int> t=q[hh++];
        
        //每一次枚举一下四个方向
        for(int i=0;i<4;i++)
        {
            //找到下一个点的坐标,由于分别枚举了四个不同的方向,
            //所以四个放向都会囊括在内,并且找到最优解
            int x=t.first+dx[i],y=t.second+dy[i];
            /*
            x、y没出边界,并且向这个方向扩展时g[x][y]==0(符合题意时),
            并且扩展后的点之前没有被用过时(最短路,一个点只走一次时所走的路径最短)
            */
            if(x>=0 && x<n && y>=0 && y<m && g[x][y]==0 && d[x][y]==-1)
            {
                //那么这个点的距离等于上个点到原点的距离+1;
                d[x][y] = d[t.first][t.second]+1;
                //把这个点的坐标加进来
                q[ ++ tt] = {x,y};
            }
        }
    }
    
    return d[n-1][m-1];
}
int main()
{
    cin >> n >> m;
    for(int i=0;i<n;i++)
     for(int j=0;j<m;j++)
      cin >> g[i][j];
    
    cout << bfs() << endl;
    return 0;
}

②:队列:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 105;
int n,m;
int g[N][N];
int d[N][N];
typedef pair<int,int> PII;

PII p[N*N];

int dfs()
{
    int hh=0,tt=0;
    
    memset(d,-1,sizeof d);
    d[0][0]=0;
    p[0]={0,0};
    
    while(hh<=tt)
    {
        PII t=p[hh++];
        
        int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
        
        for(int i=0;i<4;i++)
        {
            int x=t.first+dx[i],y=t.second+dy[i];
            if(x>=0 && x<n && y>=0 && y<m && g[x][y]==0 && d[x][y]==-1)
            {
                d[x][y]=d[t.first][t.second]+1;
                p[++tt]={x,y};
            }
        }
    }
    return d[n-1][m-1];
}
int main()
{
    cin >> n >> m;
    for(int i=0;i<n;i++)
     for(int j=0;j<m;j++)
      cin >> g[i][j];
    
    cout << dfs();
    
    return 0;
}

题目:

845. 八数码 - AcWing题库

思路: 

这里每种不同的状态我们直接用字符串来记录,然后利用unordered_map<string, int> d;将每种字符串映射到不同的int值里,来达到记录每种状态(字符串)的目的。

'x'的上、下、左、右 每次向空格'x'里移动一次,称为一个操作
我们可以把所有状态看成是图论当中的一个节点
然后每变换一次就会成为一个新的节点
最终的状态为最终节点
上一个节点与下一个节点的连线的权重为1
那么从最开始的节点到最终的节点的长度就是最短路径
难点:
①状态表示比较复杂:如何将每一个矩阵的状态存到队列里面
②如何来记录每一个状态的距离
③如何做状态转移{
    1)先恢复成矩阵的形式,2)再将空格x的上下左右分别枚举,移到x的位置上去
    3)再将矩阵恢复成字符串的形式,这时就会形成一个新的字符串了(如果之前没有被形成的话)
    
}
  ①可以用一个字符串来表示这样一种状态。
  队列直接用queue<string>来表示。②距离直接用哈希表来记录:unordered_map<string>来存。

代码:

#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<queue>

using namespace std;

int bfs(string start)
{
    //end是最终要求的状态,不同的字符串对应不同的状态
    string end="12345678x";
    
    queue<string> q;
    //距离数组,每一个string状态映射一个int值
    unordered_map<string,int> d;
    
    q.push(start);
    //一开始起点到终点的距离为0
    d[start]=0;
    
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    
    while(!q.empty())
    {
        //记录当前的状态
        auto t=q.front();
        q.pop();
        
        //记录当前的坐标
        int distance=d[t];
        //如果找到了,返回距离
        if(t==end) return distance;
        
        //状态转移,看一下当前的状态能变成哪些状态
        //先找到'x'在字符串中所对应的下标
        int k=t.find('x');
        int x=k/3,y=k%3;//找到'x'的坐标,下一步的操作就是移动'x'的上、下、左、右坐标,
        //进而形成新的状态
        for(int i=0;i<4;i++)
        {
            //上下左右的坐标{a,b}
            int a=x+dx[i],b=y+dy[i];
            if(a>=0 && a<3 && b>=0 && b<3)
            {
                //'x'所在字符串为t[k],
                //二维转换成一维:a*3+b
                //交换两种状态(更新当前的状态,使其等于最新的状态)
                swap(t[k],t[a*3+b]);
                //如果更新完之后的t之前没有被搜过的话,即更新完后的状态之前没出现过的话
                if(!d.count(t))
                {
                    //更新完后的状态到原始状态的距离=之前的距离+1;
                    d[t]=distance+1;
                    //新的状态加到队列当中去
                    q.push(t);
                }
                //恢复原状,以便下次循环判断新的状态
                swap(t[k],t[a*3+b]);
            }
        }
        
    }
    //没找到
    return -1;
}

int main()
{
    //string表示状态
    string start;
    for(int i=0;i<9;i++)
    {
        char c;
        cin >> c;
        //记录初始状态
        start+=c;
    }
    
    cout << bfs(start) << endl;
    
    return 0;
    
    
}

tips:


在C++中,unordered_map<string, int> d; 定义了一个名为 d 的 unordered_map(无序映射),
其键(key)是 string 类型,值(value)是 int 类型。这个 unordered_map 不保证元素的顺序与插入顺序相同,
但它允许你以非常接近O(1)的平均时间复杂度来查找、插入和删除元素(基于哈希表实现)。

这个 unordered_map 本身并不返回 int 值。
它是一个容器,可以存储多个键值对(key-value pairs),
其中每个键是唯一的 string,每个键映射到一个 int 值。

向上(-1,0)、下(1,0)、左(0,-1)、右(0,1),这里可以用两个一维数组来简化代码:dx[4]={-1,0,1,0},dy[4]={0,1,0,-1}

(dx[1],dy[1])即代表向上

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

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

相关文章

adb的常见操作和命令

最近学习adb的时候&#xff0c;整理了一些adb的使用场景&#xff0c;如&#xff1a;adb与设备交互&#xff0c;adb的安装、卸载&#xff0c;adb命令启动&#xff0c;通过命令清除缓存&#xff0c;文件传输和日志操作。 adb的两大作用&#xff1a;在app测试的时候可以提供监控日…

如何高效测试防火墙的NAT64与ALG应用协议转换能力

在本文开始介绍如何去验证防火墙&#xff08;DUT&#xff09;支持NAT64 ALG应用协议转换能力之前&#xff0c;我们先要简单了解2个比较重要的知识点&#xff0c;即&#xff0c;NAT64和ALG这两个家伙到底是什么&#xff1f; 网络世界中的“翻译官” - NAT64技术 简而言之&…

【Linux安全】iptables防火墙(二)

目录 一.iptables规则的保存 1.保存规则 2.还原规则 3.保存为默认规则 二.SNAT的策略及应用 1.SNAT策略的典型应用环境 2.SNAT策略的原理 2.1.未进行SNAT转换后的情况 2.2.进行SNAT转换后的情况 3.SNAT策略的应用 3.1.前提条件 3.2.实现方法 三.DNAT策略及应用 1…

学习笔记——数据通信基础——数据通信网络(网络工程师)

网络工程师 网络工程&#xff0c;就是围绕着网络进行的一系列的活动&#xff0c;包括∶网络规划、设计、实施、调试、排错等。网络工程设计的知识领域很宽广&#xff0c;其中路由和交换是计算机网络的基本。 网络工程师∶是在网络工程领域&#xff0c;掌握专业的网络技术&…

Go 使用 RabbitMQ---------------之一

RabbitMQ 是一种消息代理。消息代理的主要目的是接收、存储并转发消息。在复杂的系统设计和微服务架构中,RabbitMQ 经常被用作中间件来处理和转发系统之间的消息,以确保数据的一致性和可靠性。正是因为提供了可靠的消息机制、跟踪机制和灵活的消息路由,常常被用于排队算法、…

SAP PP学习笔记 - 错误 CX_SLD_API_EXCEPTION - Job dump is not fully saved (too big)

我这个错误是跑完MRP&#xff0c;然后在MD04查看在库/所有量一览&#xff0c; 点计划手配&#xff08;Planned order 计划订单&#xff09;生成 制造指图&#xff08;Production order 生产订单&#xff09;&#xff0c; 到目前这几步都OK&#xff0c;然后在制造指图界面点保…

View->Bitmap缩放到自定义ViewGroup的任意区域

Bitmap缩放和平移 加载一张Bitmap可能为宽高相同的正方形&#xff0c;也可能为宽高不同的矩形缩放方向可以为中心缩放&#xff0c;左上角缩放&#xff0c;右上角缩放&#xff0c;左下角缩放&#xff0c;右下角缩放Bitmap中心缩放&#xff0c;包含了缩放和平移两个操作&#xf…

Golang | Leetcode Golang题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; func generate(numRows int) [][]int {ans : make([][]int, numRows)for i : range ans {ans[i] make([]int, i1)ans[i][0] 1ans[i][i] 1for j : 1; j < i; j {ans[i][j] ans[i-1][j] ans[i-1][j-1]}}return ans }

NXP i.MX8系列平台开发讲解 - 3.12 Linux 之Audio子系统(一)

专栏文章目录传送门&#xff1a;返回专栏目录 目录 1. Audio 基础介绍 1.1 音频信号 1.2 音频的处理过程 1.3 音频硬件接口 1.3 音频专业术语解释 2. Linux Audio子系统介绍 3. Linux Audio子系统框架 Linux嵌入式系统中的音频子系统扮演着至关重要的角色&#xff0c;它涉…

Vue3+vite项目中使用mock模拟接口

安装依赖 分别安装vite-plugin-mock跟mockjs两个插件 npm install -D vite-plugin-mock mockjs vite.config.ts中添加配置&#xff0c;主要是红色标记的配置 注意此处如果配置出错可能是vite-plugin-mock依赖的版本有问题&#xff0c;重新安装一下依赖指定版本即可&#xf…

MX Component基础使用(多点位读取,多点位写入)

步骤&#xff0c;先连接PLC&#xff0c;然后在填入对应的点位 D10 然后去读取。 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;us…

国产卫星星座,为什么一定要“走出去”?

今天这篇文章&#xff0c;我们来聊聊卫星和星座。 2024年行将过半&#xff0c;全球卫星通信产业的发展&#xff0c;又有了新的变化。 在卫星星座方面&#xff0c;各大企业的竞争博弈全面进入白热化阶段。卫星的发射速度在不断加快&#xff0c;而全球星座项目的数量和规模也在持…

nano机器人2:机械臂的视觉抓取

前言 参考链接: 【机械臂入门教程】机械臂视觉抓取从理论到实战 GRCNN 通过神经网络&#xff0c;先进行模型训练&#xff0c;在进行模型评估。 机械臂逆运动学求解 所有串联型6自由度机械臂均是可解的&#xff0c;但这种解通常只能通过数值解法得到&#xff0c;计算难度大&am…

Java | Leetcode Java题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret new ArrayList<List<Integer>>();for (int i 0; i < numRows; i) {List<Integer> row new…

Unity之如何使用Localization来实现文本+资源多语言

前言 使用Unity实现本地化&#xff08;Localization&#xff09;功能 在当今的游戏开发中&#xff0c;支持多语言已成为一项基本需求。Unity作为主流的游戏开发引擎&#xff0c;提供了强大的本地化工具&#xff0c;使开发者能够方便地为游戏添加多语言支持。本文将介绍如何在U…

JavaSE:StringBuilder和StringBuffer类

1、引言 在上一篇文章中&#xff0c;我们理解了字符串的常用方法&#xff0c;细心的同学大概已经发现&#xff0c;不管是将字符串中的字符转变为大写或小写&#xff0c;或是完成字符串的替换&#xff0c;又或是去除空白字符等等&#xff0c;只要涉及到字符串的修改&#xff0c…

js中金额进行千分以及toFixed()保留两位小数丢失精度的问题

1、金额进行千分 function commafy(num) { if ((num "").trim() "") { return ""; } if (isNaN(num)) { return ""; } num num ""; if (/^.*\..*$/.test(num)) { const pointIndex num.lastIndexOf("."); co…

[C][动态内存分配][柔性数组]详细讲解

目录 1.动态内存函数的介绍1.malloc2.free2.calloc4.realloc 2.常见的动态内存错误3.C/C程序的内存开辟4.柔性数组1.是什么&#xff1f;2.柔性数组的特点3.柔性数组的使用4.柔性数组的优势 1.动态内存函数的介绍 1.malloc 函数原型&#xff1a;void* malloc(size_t size)功能…

从0开始学会做标书:新手学习做标书制作必修(95节课)

入门框架 电子标书 商务标书 文档排版 技术标书 实操演示 你是否也有同样的问题 1、做标书公司没人教、没人带? 2、如何看懂招标文件? 3、小白零基础能不能学习做标书? 4、商务标、技术标如何得高分? 5、做标书需要什么软件? 6、如何制作电子标书? 7、如何避…

您提供或引用的参考资料无法对应怎么解决

在创建或编辑百度百科词条时&#xff0c;经常会遇到“您提供或引用的参考资料无法对应”的问题。以下百科参考网shaoshai是解决这个问题的一些方法&#xff1a; 检查和修正参考资料 首先&#xff0c;您需要仔细检查提供的参考资料&#xff0c;确保它们与您的内容相对应。如果发…