BFS和队列例题

poj2251Dungeon Master

最简单的BFS求最短距离,只是改一下方向数组就可以,二维数组改为三维数组

下面是AC代码

对了,下面用的c++队列,其实很简单,就只有几种操作:

先介绍队列的定义   queue<类型名>变量名,如

queue<int>q,queue或queue<node>que;(struct node(结构体类型));

1、 q.front()      取出队首元素

2、   q.empty()    判断是否为空,时空返回1

3、   q.pop()       删除队首元素

4、   q.push(变量)加入变量      

复制代码
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 1000000007
17 #define judge(x,y,z) !vis[x][y][z]&&map[x][y][z]!='#'&&x>=0&&x<l&&y>=0&&y<m&&z>=0&&z<n
18 int d[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
19 bool vis[35][35][35];
20 char map[35][35][35];
21 int l,m,n;
22 struct node
23 {
24     int x,y,z;
25     int step;
26 };
27 int  BFS(int x,int y,int z)
28 {
29     mem(vis);
30     queue<node>q;
31     node u;
32     u.x=x;u.y=y;u.z=z;
33     u.step=0;
34     q.push(u);
35     while(!q.empty())
36     {
37         u=q.front();
38         if(map[u.x][u.y][u.z]=='E')return u.step;
39         q.pop();
40         int i;
41         for(i=0;i<6;i++)
42         {
43             node v;
44             v.x=u.x+d[i][0];v.y=u.y+d[i][1];
45             v.z=u.z+d[i][2];
46             if(judge(v.x,v.y,v.z))
47             {
48                 vis[v.x][v.y][v.z]=true;
49                 v.step=u.step+1;
50                 q.push(v);
51             }
52         }
53     }
54     return 0;
55 }
56 int main()
57 {
58     while(~scanf("%d%d%d%*c",&l,&m,&n))
59     {
60         mem(map);
61         if(!m&&!n&&!l)break;
62         int i,j,k,sx,sy,sz;
63         for(i=0;i<l;i++)
64             for(j=0;j<m;j++){
65                 scanf("%s",map[i][j]);
66                 for(k=0;k<n;k++)
67                 {
68                     if(map[i][j][k]=='S')sx=i,sy=j,sz=k;
69                 }
70             }
71         int step=BFS(sx,sy,sz);
72         if(step)printf("Escaped in %d minute(s).\n",step);
73         else printf("Trapped!\n");
74     }
75     return 0;
76 }

<think>嗯,用户想了解如何用双端队列实现BFS。首先,我需要回忆一下BFS的基本概念。常规的BFS使用普通队列,按照先进先出的顺序处理节点,确保按层遍历。那双端队列(deque)有什么不同呢?双端队列允许在两端插入删除元素,这样可能在处理某些问题时更高效,比如当边的权重有0或1的情况,可以使用0-1 BFS优化。 接下来,我需要整理使用双端队列实现BFS的关键点。首先,双端队列适合处理边权值为0或1的图,这样可以将权值为0的节点插入队列前端,保持队列的单调性,减少时间复杂。然后,步骤应该是初始化双端队列,每次从前端取出节点,处理相邻节点时根据边的权值决定插入前端还是后端。这样能保证距离更短的节点优先被处理,类似于Dijkstra算法,但时间复杂度更低,O(N+M)。 然后,要考虑示例代码。比如,处理网格中的电路问题,其中转动方向需要消耗1步,而不转动则消耗0步。这种情况下,可以用双端队列来实现BFS。代码结构大致是:初始化deque,记录距离,处理当前节点时,遍历四个方向,计算新坐标消耗,根据消耗决定插入队列的位置。同时,注意边界条件已访问节点的处理。 另外,需要比较双端队列BFS普通队列BFS的区别,指出双端队列的优势在于处理特定权重的问题时更高效。还要提到适用的场景,比如电路维修、通信线路优化等,这些题目中边权有01的情况,适合用这种方法优化。 还要确保代码示例正确,符合Python语法,正确使用deque的appendleftappend方法。同时,引用用户提供的参考资料中的相关内容,比如引用[1]提到的电路维修例题通信线路问题,引用[3]中关于双端队列的基本操作适用场景。 最后,生成相关问题时要围绕双端队列BFS的应用场景、时间复杂度、与Dijkstra的区别,以及例题的扩展。比如,如何分析时间复杂度,适用哪些问题,Dijkstra相比的优缺点,以及如何处理更复杂的边权情况。 需要检查是否有遗漏的关键点,比如正确使用双端队列的条件,是否解释了为什么在处理0-1权重时更高效,以及示例代码的逻辑是否正确。同时,确保回答结构清晰,步骤明确,符合用户要求的格式,特别是数学表达式代码块的使用要正确。</think>### 使用双端队列实现 BFS 的方法及示例 #### 1. 双端队列 BFS 的核心思想 双端队列 BFS(也称 **0-1 BFS**)用于解决**边权仅有 0 或 1 的图的最短路径问题**。通过将权值为 0 的边对应的节点插入队列前端,权值为 1 的边对应的节点插入队列后端,保证队列的单调性,时间复杂度可优化至 $O(N + M)$,优于普通 BFS Dijkstra 算法[^1][^3]。 #### 2. 实现步骤 1. **初始化双端队列**,将起点插入队列前端,距离标记为 0。 2. **循环处理队列**: - 从队列前端取出节点。 - 遍历相邻节点,根据边权值选择插入位置: - 边权为 0:插入队列前端(距离不变)。 - 边权为 1:插入队列后端(距离 +1)。 3. **记录最短距离**,避免重复访问。 #### 3. 示例代码(电路维修问题) ```python from collections import deque def bfs(grid): m, n = len(grid), len(grid[0]) dist = [[float('inf')] * n for _ in range(m)] dist[0][0] = 0 dq = deque() dq.append((0, 0)) # 方向与对应期望的电路方向('/'或'\') dirs = [(-1, -1, '/'), (-1, 1, '\\'), (1, -1, '\\'), (1, 1, '/')] while dq: x, y = dq.popleft() for dx, dy, expect in dirs: nx, ny = x + dx, y + dy if 0 <= nx < m and 0 <= ny < n: cost = 0 if grid[(x + nx) // 2][(y + ny) // 2] == expect else 1 if dist[nx][ny] > dist[x][y] + cost: dist[nx][ny] = dist[x][y] + cost if cost == 0: dq.appendleft((nx, ny)) # 权值为 0,插入前端 else: dq.append((nx, ny)) # 权值为 1,插入后端 return dist[m-1][n-1] if dist[m-1][n-1] != float('inf') else -1 ``` #### 4. 关键点分析 - **适用场景**:边权为 0 或 1 的图(如电路维修需旋转次数最少、通信线路的建造成本优化)[^3]。 - **优势**:相比普通 BFS 的 $O(N^2)$,时间复杂度降至线性 $O(N + M)$[^3]。 - **与 Dijkstra 对比**:无需优先队列,通过双端队列直接保证路径单调性。 #### 5. 与普通队列 BFS 的区别 | 特性 | 双端队列 BFS | 普通队列 BFS | |--------------------|---------------------|--------------| | 边权限制 | 0 或 1 | 无 | | 时间复杂度 | $O(N + M)$ | $O(N^2)$ | | 插入方式 | 前端或后端 | 仅后端 | | 应用场景 | 最短路径优化 | 层序遍历 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值