数据结构与算法——BFS(广度优先搜索)

news2024/9/20 15:39:25

算法介绍:

广度优先搜索(Breadth-First Search,简称BFS)是一种遍历或搜索树和图的算法,也称为宽度优先搜索,BFS算法从图的某个节点开始,依次对其所有相邻节点进行探索和遍历,然后再对这些相邻节点的相邻节点进行探索,直到遍历完所有的节点。BFS算法使用队列来辅助实现,将起始节点放入队列中,然后依次取出队列中的节点,访问其相邻节点,并将其加入队列。这样可以保证从起始节点出发,依次按照距离顺序遍历节点。BFS常用于寻找最短路径,因为它按照从起点到每个节点的距离来探索节点。

在ACM、蓝桥杯等著名竞赛中BFS算法是比较重要的,特别是在蓝桥杯中每一年几乎都要考DFS/BFS算法。BFS算法在OI赛中用处非常大,可以通过DFS/BFS暴力的方式可以拿到部分分数,蓝桥杯一般可以拿到20%的分数,有的甚至高达50%,是暴力得分的不二之选。

基本步骤:

BFS算法通常使用队列来实现,BFS算法的具体步骤如下:

  1. 创建一个队列,将起始节点加入队列;
  2. 创建一个集合,用于存储已经访问过的节点;
  3. 从队列中取出一个节点,并将其标记为已访问;
  4. 访问该节点的所有相邻节点,如果相邻节点未被访问,则将其加入队列;
  5. 重复步骤3和步骤4,直到队列为空。

BFS算法可以用来解决一些问题,例如图的遍历、最短路径搜索等。由于BFS算法保证了按照距离顺序遍历节点,因此可以用来寻找最短路径。另外,BFS算法还可以用来判断图是否连通,即从一个节点是否可以到达另一个节点。


图解算法:

下面放一张我们学校ACM在大一培训时使用的一张动态BFS/DFS步骤图。注:红色遍历为BFS、黄色遍历为DFS。(绿色为起点,紫色为终点,黑色为障碍物)

由上图中我们可以看出,BFS的遍历为四周扩散,用我们学长的话说就是周围每个点都尝试一下,无脑走,直到找到终点。由此我们可以看出来,BFS这种无脑走必定会导致时间复杂度非常高,如果终点离起点非常远,那么几乎每个点都要遍历一下,这样的话BFS这种算法就不适合了,BFS适合于点少的图,求最短距离之类的。BFS一般通过队列来实现。

下面我们将以5*5的网格,考虑{上、右上、右、右下、下、左下、左、左上}八个方向,遍历顺序为{上、右上、右、右下、下、左下、左、左上}由上开始顺时针方向,顺序可按照自己的想法,顺序不一定固定,给大家模拟实现一下过程。

:为方便表示,对于下面的叫法特此说明,起点.上表示起点上面的格子,起点.上右表示起点右上方的格子,其他方向类似,起点.上.上右表示起点的上面格子的右上方格子。

第一步:

初始起点入队,标记起点vis[起点]==true,说明起点已经被访问了,判断起点是否为终点,起点出队,很明显不是那么从起点周围按照{上、右上、右、右下、下、左下、左、左上}的顺序八个方向遍历每一个格子,将它们一一入队,并且将它们标记为已经访问过了,即vis[八个方向]=true。

第二步:

由于我们第一步按照{上、右上、右、右下、下、左下、左、左上}的顺序入队的,此时队中的顺序是起点的{上、右上、右、右下、下、左下、左、左上}方向,那么此时出队的第一个是{上}方向,我们去遍历{上}方向的八个方向,由于{上}方向的八个方向中{上、右上、左上}三个方向下标越界,其他的都已经被访问过了,不合法,直接continue忽略掉,{上}方向遍历完成,{上}方向出队。

第三步:

此时要出队的为{上右}方向,先标记{上右}方向,然后遍历{上右}方向的八个方向,我们发现只有{上右}方向的{右}方向跟{下右}方向是合法的,其他的方向要么下标越界,要么已经被访问了,那么把{上右}方向的{右}方向跟{上右}方向的{下右}方向入队,并且标记它们的vis为true。

第四步:

此时队头的为起点的{右}方向,将它出队,判断它不是终点,那么遍历它的八个方向,发现只有它的{右下}方向是合法的,其他方向都已经被标记过了。那么将vis[右下]标记为true,将它的右下方向入队。

第五步:

此时队头的为起点的{下右}方向,将它出队,判断它不是终点,那么遍历它的八个方向,发现它的{右下、下、左下}方向是合法的,其他方向都已经被标记过了。那么将vis[右下、下、左下]标记为true,并且将其入队。此时我们发现它的右下方向是终点了,已经在栈队当中,再经过八次出队,那么就是这个出队的点就是终点了,判断完成后此时BFS搜索就结束了,由于下面都是相同的出队入队步骤,下面不再详解。


算法模板:

首先我们需要一个队列来辅助BFS实现,还需要一个初始化的输入数组,还有一个标记数组。先找到BFS的起点跟终点,确定好之后,先把起点vis==true,把起点入队,然后进入BFS函数,进入BFS函数一般先是一个大while循环,来管理队列的入队、出队。由于点都是二维的,我们一般都是用pair或者结构体来表示点,新建一个点来存储队头的信息,存完就可以让队头出队了。然后判断是否到达了目标结点,一个if判断,下面就是跟dfs一样,一个for循环遍历周围所有的点,不合法的直接continue掉,合法的标记完vis后入队,有的题目会有回溯,像在部分最短路搜索。

queue<node> q;
void bfs(){
	while(!q.empty()){
		node tmp=q.top();//node为(x,y)结构体
		q.pop();//出队
		if(到达目标终点){
			更新
			return;
		}
		//有的会有剪枝
		for(int i=0;i<m;i++){//m个方向
			int dx=tmp.x+bx[i];
			int dy=tmp.y+by[i];
			if(下标越界){
				continue;
			}
			if(已经被标记过了){
				continue;
			}
			//否则就是合法的
			vis[dx][dy]=1;//先标记
			q.push(node{dx,dy});//再新点入队
		}
	}
}

算法例题:

现在各大算法刷题网站上bfs题目非常的多,bfs题目的变化也比较多,现在各种各样的题目层出不穷,bfs考察的还是主要分为图的遍历问题、最短路问题、连通块搜索等,下面博主选取几个比较具有代表性的给大家讲解一下,加深理解一下bfs算法。


一、图的遍历问题

迷宫问题
【题目描述】

一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n×n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行。同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷官的情况下能不能办到。如果起点或者终点有一个不能通行(为#),则看成无法办到。

【输入】

第1行是测试数据的组数k,后面跟着k组输入。每组测试数据的第1行是一个正整数n(1≤n≤ 100),表示迷宫的规模是n×n的。接下来是一个n×n的矩阵,矩阵中的元素为.或者#。再接下来一行是4个整数ha,la,hb,lb,描述A处在第ha行,第la列,B处在第hb行,第lb列。注意到ha,la,hb,lb全部是从0开始计数的。

【输出】

k行,每行对应一个输出,如果能到达则输出"YES",否则输出"NO"。

【样例】
2
3
.##
..#
#..
0 0 2 2
5
.....
###.#
..#..
###..
...#.
0 0 4 0

YES
NO
解题思路:

这类问题属于图的遍历问题,属于BFS题里面最简单的问题,直接利用BFS的思想遍历即可,判断是否能到达。之所以选这个题,是先让刚入门的小萌新熟悉一下BFS的步骤、思想。大佬可跳过此题。

AC代码:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int n,t;
char ch[105][105];
bool flag=false,vis[105][105];
int sx,sy,fx,fy;
int bx[]={0,0,1,-1},by[]={1,-1,0,0};//方向数组
struct node{
	int x,y;
};
queue<node> q;//队列
void bfs(){
	while(!q.empty()){
		node tmp=q.front();//取队头元素
		q.pop();//出队
		if(tmp.x==fx&&tmp.y==fy){//目标状态
			flag=true;
			return;
		}
		for(int i=0;i<4;i++){//周围四个方向搜索
			int dx=tmp.x+bx[i],dy=tmp.y+by[i];
			if(dx<0||dx>=n||dy<0||dy>=n){//下标越界
				continue;
		    }
			if(vis[dx][dy]){//已经被访问过
				continue;
			}
			if(ch[dx][dy]=='#'){//墙壁
				continue;
			}
			vis[dx][dy]=1;//先标记
			q.push(node{dx,dy});//再入队
		}
	}
}
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				cin>>ch[i][j];
			}
		}
		cin>>sx>>sy>>fx>>fy;
		flag=false;
		memset(vis,0,sizeof(vis));
        while(!q.empty()){//多次输入,防止上次队列的影响
			q.pop();
		}
		vis[sx][sy]=1;
		q.push(node{sx,sy});//起点入队
		bfs();
		cout<<(flag?"YES":"NO")<<endl;
	}
	return 0;
}

二、最短路问题

AcWing 1102. 移动骑士

给定一个 n∗n 的棋盘,以及一个开始位置和终点位置。

棋盘的横纵坐标范围都是 0∼n−1。

将一个国际象棋中的骑士放置在开始位置上,请问将它移动至终点位置至少需要走多少步。

一个骑士在棋盘上可行的移动方式如下图所示:

QQ截图20191016061524.png

输入格式

第一行包含整数 T,表示共有 T 组测试数据。

每组测试数据第一行包含整数 n,表示棋盘大小。

第二行包含两个整数 x,y 用来表示骑士的开始位置坐标 (x,y)。

第三行包含两个整数 x,y 用来表示骑士的终点位置坐标 (x,y)。

输出格式

每组数据输出一个整数,表示骑士所需移动的最少步数,每个结果占一行。

数据范围

4≤n≤300
0≤x,y≤n−1

输入样例:
3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1
输出样例:
5
28
0
解题思路:

这道题跟马走日那一题几乎是一样的,但是不一样的是这道题是求的最小步数。这就是最短路问题了。还是跟之前的BFS步骤一样,就是在目标状态那里多了一个更新最小步数。这道题比前面的图的遍历问题难一点点,注意,BFS是不需要回溯的,否则会陷入死循环。

AC代码:
#include<iostream>
#include<cstring>
#include<queue>

using namespace std;
int t,n;
int sx,sy,fx,fy;//(sx,sy)起点,(fx,fy)终点
struct node{//点结构体
	int x;
	int y;
	int dep;//步数
}Node;
int dx[]={1,1,2,2,-1,-1,-2,-2};//方向数组
int dy[]={2,-2,1,-1,2,-2,1,-1};
bool vis[305][305];//标记数组
int sum=0x3f3f3f;//最小步数
queue<node> q;

void bfs(){
	while(!q.empty()){
		auto tmp=q.front();
		q.pop();
		if(tmp.x==fx&&tmp.y==fy){//目标状态更新最小步数
			sum=min(sum,tmp.dep);
			return;
		}
		for(int i=0;i<8;i++){//八个方向遍历
			Node.x=tmp.x+dx[i];
			Node.y=tmp.y+dy[i];
			if(Node.x<0||Node.y<0||Node.x>=n||Node.y>=n){//下标越界
				continue;
			}
			if(vis[Node.x][Node.y]==1){//已经被访问过
				continue;
			}
			Node.dep=tmp.dep+1;//步数更新
			vis[Node.x][Node.y]=1;//先标记
			q.push(Node);//再入队
		}
	}
}

int main(){
	cin>>t;
	while(t--){
		memset(vis,false,sizeof(vis));//多组输入置0
		sum=0x3f3f3f;//初始最大值
		cin>>n>>sx>>sy>>fx>>fy;
		vis[sx][sy]=1;//先标记起点
		while(!q.empty()){//清空队列
			q.pop();
		}
		q.push(node{sx,sy,0});//起点步数为0
		bfs();
		cout<<sum<<endl;
	}
	return 0;
}

洛谷 P1379 八数码难题
题目描述

在 3×3 的棋盘上,摆有八个棋子,每个棋子上标有 1 至 8 的某一数字。棋盘中留有一个空格,空格用 0 来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为 123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入格式

输入初始状态,一行九个数字,空格用 0 表示。

输出格式

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数。保证测试数据中无特殊无法到达目标状态数据。

输入 

283104765

输出 

4
样例解释

图中标有 0 的是空格。绿色格子是空格所在位置,橙色格子是下一步可以移动到空格的位置。如图所示,用四步可以达到目标状态。并且可以证明,不存在更优的策略。

解题思路:

这道题在博主做题的感觉来说,题目质量是非常高的,思维也非常有高度,建议大家好好学一下。八数码非常类似于中国的数独游戏。在解决此题时一个布局对应一个字符串也就是一个状态,可以理解为一个布局转换为目标布局所需要的最小步数。

下面讲解一下如何解决此题,我们发现每一个字符串就是一个状态,最短距离还需要记录步数,那么我们就想到了map键值映射,由一个字符串对应初始状态到此状态的最小步数。例如:d["123048567"]=2表示由初始状态到目标状态最小步数为2步完成。其次是‘0’字符一维下标跟二维下标位置转换的技巧,我们发现每一次都是‘0’字符(空格)与四个方向的数字进行交换,属于空格的BFS,对于一维下标可以通过除3为横坐标,模3为纵坐标(3*3棋盘),由二维转为一维坐标倒过来即可,即:3*横坐标+纵坐标。刚开始可以使用find()函数查找‘0’字符的下标,然后转化为布局中的二维坐标。每完成一步就要交换格子,交换完成就得到一种新的布局,那么我们可以用count()函数去map里面查找,如果有这种状态说明之前用更小的步数就已经到达过了,没必要更新了。如果没有这种状态,那么我们就为它赋值最小步数。最后还要还原,对于这个题来说是必要的,因为四个方向搜索都是以‘0’为基础的,for循环一次把他改变了,后面的3次循环就在它前一个状态的基础上。这样交换操作就乱了。

视频讲解: 请看B站up主董晓算法,—>>点击直达<<—,博主感觉董晓老师讲的非常好,本题思路按照董晓老师讲解来写的。大家可以去看看,下面第二张图片来自董晓老师讲解。

AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<unordered_map>

using namespace std;

int dx[]={-1,0,1,0},dy[]={0,1,0,-1};//方向数组
unordered_map<string,int> d;//考虑map键值对映射,状态映射步数
queue<string> q;//棋盘状态布局

int bfs(string strat){
	string end="123804765";//目标状态
	q.push(strat);//初始状态
	d[strat]=0;
	while(q.size()){
		auto s=q.front();
		q.pop();
		if(s==end){//目标状态
			return d[s];
		}
		int k=s.find('0');//下标位置转化
		int x=k/3;
		int y=k%3;
		for(int i=0;i<4;i++){//四个方向搜索
			int a=x+dx[i];
			int b=y+dy[i];
			if(a<0||a>=3||b<0||b>=3){//下标越界
				continue;
			}
			int distance=d[s];//记录步数
			swap(s[k],s[3*a+b]);//交换
			if(!d.count(s)){//新的布局
				d[s]=distance+1;
				q.push(s);
			}
			swap(s[k],s[3*a+b]);//还原
		}
	}
	return -1;//无法到达
}

int main(){
	string strat;
	for(int i=0;i<9;i++){
		char ch;
		cin>>ch;
		strat+=ch;
	}
	cout<<bfs(strat)<<endl;
	return 0;
}

三、连通块问题

第十四届省赛大学B组(C/C++)岛屿个数

到目前为止我做过像连通块问题的题用BFS解的就这一个比较好,这一道题跟连通块有结合,博主才把它归到了连通块问题来。具体的讲解跟AC代码,请看我这一篇文章,文章单独讲解了这一道题,由于文章长度限制这里不再详解,请移步下面链接。

第十四届省赛大学B组(C/C++)岛屿个数-CSDN博客文章浏览阅读1.1k次,点赞30次,收藏14次。这不是普通的DFS/BFS搜索题,看着很像最少连通块,但是题目中又有了新的定义就是在陆地环里面(被陆地包围)也算属于此外围岛屿,那么我们就也要判定这种环岛屿,博主的思路是先BFS也可DFS找出连通块的个数(四个方向),建一个vector把连通块的起点存进去,方便去找环岛屿,只要有一个起点(或者此连通块任意一个点),此连通块的点便可通过移动一网打尽,再BFS(或者DFS)判定该岛屿是否属于这种环岛屿,不属于就结果加一,属于就不用加。对于 100% 的评测用例,1≤T≤10,1≤M,N≤50。https://blog.csdn.net/m0_73633807/article/details/137248445?spm=1001.2014.3001.5501


图形搜索算法还有一种是DFS,请看博主上一篇文章数据结构与算法——DFS(深度优先搜索)

制作不易,如果对你有所帮助请三连支持博主持续创作,感谢各位大佬的支持。

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

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

相关文章

第T8周:使用TensorFlow实现猫狗识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 一、前期工作1.设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据 二、数据预处理1、加载数据2、再次检查数据3. 配置数据集4…

低代码开发的崛起:机遇与挑战

近年来&#xff0c;“低代码”开发平台的迅速崛起&#xff0c;已经成为IT行业中不可忽视的趋势。这些平台承诺让非专业人士也能快速构建应用程序&#xff0c;通过减少代码编写的需求&#xff0c;大幅提高开发效率。对于许多企业而言&#xff0c;低代码开发工具成为了一个加速数…

Real-Time Open-Vocabulary Object Detection:使用Ultralytics框架进行YOLO-World目标检测

Real-Time Open-Vocabulary Object Detection&#xff1a;使用Ultralytics框架进行YOLO-World目标检测 前言相关介绍前提条件实验环境安装环境项目地址LinuxWindows 使用Ultralytics框架进行YOLO-World目标检测进行训练进行预测进行验证 扩展目标跟踪设置提示 参考文献 前言 由…

windows核心编程 第14章,虚拟内存:获取系统信息

windows核心编程 第14章&#xff0c;虚拟内存&#xff1a;获取系统信息 14,获取系统消息 文章目录 windows核心编程 第14章&#xff0c;虚拟内存&#xff1a;获取系统信息14.1 系统信息 14.1 系统信息 许多操作系统的值是根据主机而定的&#xff0c;比如页面的大小&#xff0…

无人机挂载垂直抛投灭火弹技术详解

随着城市化进程的加快&#xff0c;高层建筑、森林、化工园区等区域火灾防控难度日益增大。传统消防手段在面对复杂地形或高层火灾时&#xff0c;往往存在响应速度慢、作业难度大、人员安全风险高等问题。无人机挂载垂直抛投灭火弹技术的出现&#xff0c;为高效、安全、精准的火…

conda install vs pip install

1背景 最近使用pyinstaller打包python程序&#xff0c;启动程序的时候&#xff0c;发现了以下的报错信息 Failed to execute script "pyi_rth_pkgres" due to unhandled dll load failed while importing pyexpat后面查阅了相关文档&#xff0c;比如根据stackoverf…

Vue3+Ts封装下拉懒加载自定义指令

文件夹目录如下: 使用方式: <template><divclass="time-line"v-infinite-scroll="{loadMore: loadMoreItems,threshold: 100 // 当滚动到距离底部 100 像素时触发加载}"> </div> </template><script lang="ts" se…

7次多项式对若干个点进行拟合,并生成图像|MATLAB实现

文章目录 拟合运行结果完整代码拟合 MATLAB对数据进行拟合的意义是通过数学模型和统计方法对实际数据进行分析和预测。拟合可以帮助我们理解数据背后的规律和趋势,从而做出科学决策。 拟合的意义 揭示数据的规律 预测未来趋势 数据修正和异常检测 数据分析和模型验证 总之,…

Prometheus+Grafana保姆笔记(2)——监控Spring Boot微服务程序

Prometheus Grafana 的组合在微服务项目中可以完成许多DevOps任务&#xff0c;它们共同提供了强大的监控和可视化功能。 我们陆续介绍Prometheus Grafana 的相关用法。 上一期&#xff0c;我们介绍了PrometheusGrafana的安装&#xff0c; PrometheusGrafana保姆笔记&#…

javaFx桌面程序开发代码示例

程序效果&#xff1a; 弹窗内容&#xff1a; 1.启动类 HelloJavaFX&#xff1a; import javafx.application.Application; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene…

赵本山:你把这玩意借我带上,黄晓娟:驴蒙脸你要带这个?--小品《麻将豆腐》(中3)的台词与解说

赵本山&#xff1a;你把这玩意借我带上&#xff0c;黄晓娟&#xff1a;驴蒙脸你要带这个&#xff1f; --小品《麻将豆腐》&#xff08;中3&#xff09;的台词与解说 &#xff08;接上&#xff09; 黄晓娟&#xff08;饰演小姨子&#xff09;&#xff1a;忘了麻将 赵本山&…

车载客流计数器在公交系统中的应用

车载客流计数器在公交系统中的应用&#xff0c;已成为提升运营效率与服务质量的关键工具。随着大数据概念的深入人心&#xff0c;人们愈发认识到数据在决策中的核心地位。公交车客流统计的引入&#xff0c;正是基于这一认识&#xff0c;旨在为公交车辆的运营组织提供详实、精准…

MySQL:表的设计原则和聚合函数

所属专栏&#xff1a;MySQL学习 &#x1f48e;1. 表的设计原则 1. 从需求中找到类&#xff0c;类对应到数据库中的实体&#xff0c;实体在数据库中表现为一张一张的表&#xff0c;类中的属性对应着表中的字段 2. 确定类与类的对应关系 3. 使用SQL去创建具体的表 范式&#xff1…

【Linux多线程】线程同步 与 生产者消费者模型(无锁化模型)

文章目录 1. Linux线程同步1.1 条件变量1.2 同步概念与竞态条件1.3 条件变量函数示例代码1:示例代码2 1.4 为什么 pthread_ cond_ wait 需要互斥量1.5 条件变量使用规范 2. 生产者消费者模型3. 读者 写者 问题3.1 读写锁3.2 读写锁的相关接口 4. 扩展&#xff1a;无锁化模型4.1…

Python 如何创建和解析 XML 文件

XML&#xff08;可扩展标记语言&#xff09;是一种广泛使用的标记语言&#xff0c;主要用于存储和传输数据。它具有结构化、层次化的特点&#xff0c;常被用作数据交换格式。Python 提供了多种工具和库来处理 XML 文件&#xff0c;包括创建、解析和操作 XML 文档。 一、XML 简…

免费webp转jpeg或gif工具

1、”“添加webp文件&#xff1b;”-“移除webp文件&#xff1b;”>>“开始转换&#xff1b;”X“清空内容。 也可以把想要转换的文件全选&#xff0c;拖进窗口里。 2、默认将webp文件转换成同名的png文件放在原来的文件夹里。如果不是静态图片&#xff0c;则自动尝试转…

案例:ZooKeeper + Kafka消息队列集群部署

目录 消息队列 概念 使用场景 不适宜 适宜 消息队列的特征 存储 异步 异步的优点 同步 为什么需要消息队列 解耦 作用 冗余 扩展性 灵活性 峰值处理能力 可恢复性 顺序保证 Kafka 概念 Kafka技术名词 &#xff08;1&#xff09;Broker &#xff08;2&a…

基于Orangepi全志H616智能视觉垃圾分类系统

目录 一、功能需求 二、Python的安装和环境搭建 三、Python基础 3.1 Python的特点&#xff1a; 3.2 Python的基础学习&#xff1a; 3.3 字典的多层嵌套&#xff1a; 四、C语言调用Python 4.1 搭建编译环境&#xff1a; 4.2 C语言执行Python语句&#xff1a; 4.3 C语言…

22 注意力机制—Transformer

目录 TransformerTransformer 架构对比 seq2seq多头注意力(Multi-head attention)带掩码的多头注意力(Masked Multi-head attention)基于位置的前馈网络(Positionwise FFN)残差连接和归一化(Add & norm)(加 & 规范化)1、加入归一化能够更好地训练比较深的网络…

UE基础 —— 项目与模板

虚幻引擎 项目 包含游戏和应用程序的所有内容&#xff0c;并将所有内容联系在一起&#xff1b;包含磁盘上的许多文件夹和资产&#xff0c;如蓝图、材质、3D资产、动画等&#xff1b;内容浏览器与磁盘上的文件夹和文件夹结构相同&#xff1b; 每个项目都有与之关联的.uproject文…