bfs

bfs的核心思想就是把一些问题抽象成图,从一个点开始,向四周开始扩散。

一般使用队列这种数据结构,每次将一个节点周围所有节点加入队列。

相较于dfs,bfs找到的路径一定是最短的,但代价就是空间复杂度比dfs大很多。

从一个起点走到终点,问最短路径,这就是bfs的本质。

下面为bfs大致模板

int bfs()
{
    初始化队列
    初始化距离为-1
    将起点距离设为0,并加入队列
    while(队列非空){
        弹出队头元素
        遍历所有方向
            if(符合条件){
                更新距离
                将相邻节点加入队列 
            } 
    }
    return 距离 
}

模板题1[走迷宫]

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define x first
 6 #define y second
 7 
 8 typedef pair<int, int> PII;
 9 
10 const int N = 110;
11 
12 int n, m;
13 int g[N][N], d[N][N];
14 
15 int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
16 
17 int bfs()
18 {
19     queue<PII> q;
20     memset(d, -1, sizeof d);
21     d[0][0] = 0;
22     q.push({0, 0});
23     while(!q.empty()){
24         auto t = q.front();
25         q.pop();
26         for( int i = 0; i < 4; i++ ){
27             int x = t.x+dx[i], y = t.y+dy[i];
28             if(x >= 0 && x < n && y >= 0 && y < m && d[x][y]==-1 && g[x][y]==0){
29                 d[x][y] = d[t.x][t.y]+1;
30                 q.push({x, y});
31             }
32         }
33     }
34     
35     return d[n-1][m-1];
36 }
37 
38 int main()
39 {
40     scanf("%d%d", &n, &m);
41     for( int i = 0; i < n; i++ )
42         for( int j = 0; j < m; j++ )
43             scanf("%d", &g[i][j]);
44     printf("%d\n", bfs());
45     
46     return 0;
47 }

模板题2[八数码]

在一个 3×33×3 的网格中,1∼81∼8 这 88 个数字和一个 x 恰好不重不漏地分布在这 3×33×3 的网格中。

例如:

1 2 3
x 4 6
7 5 8

在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 x

例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
x 4 6   4 x 6   4 5 6   4 5 6
7 5 8   7 5 8   7 x 8   7 8 x

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式

输入占一行,将 3×33×3 的初始网格描绘出来。

例如,如果初始网格如下所示:

1 2 3 
x 4 6 
7 5 8 

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出 −1−1。

输入样例:

2  3  4  1  5  x  7  6  8

输出样例

19


题解:
将3*3的矩阵转化成字符串,从初始状态到最终状态求最短路
 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
 6 
 7 int bfs(string s)
 8 {
 9     //目标状态 
10     string end = "12345678x";
11     queue<string> q;
12     unordered_map<string, int> dis;
13     q.push(s);
14     dis[s] = 0;
15     while(!q.empty()){
16         string t = q.front();
17         q.pop();
18         int dist = dis[t];
19         if(t==end)
20             return dist;
21             //查询x在字符串中的下标,然后转化为矩阵中的坐标 
22         int k = t.find('x');
23         int x = k/3, y = k%3;
24         for( int i = 0; i < 4; i++ ){
25             int a = x+dx[i], b = y+dy[i];
26             if(a >= 0 && a < 3 && b >= 0 &&b < 3){
27                 //转移x 
28                 swap(t[k], t[a*3+b]);
29                 if(!dis.count(t)){//t状态没有出现过 
30                     q.push(t);
31                     dis[t] = dist+1;
32                 }
33                 //还原状态 ,为下一种转换做准备 
34                 swap(t[k], t[a*3+b]);
35             }
36         }
37     }
38     
39     return -1;
40 }
41 
42 int main()
43 {
44     string c, s;
45     for( int i = 0; i < 9; i++ ){
46         cin>>c;
47         s+=c;
48     }
49     cout<<bfs(s)<<endl;
50     
51     return 0;
52 }

 

上一篇:LeetCode题解随笔——DFS BFS相关题目 不断更新


下一篇:K 站中转内最便宜的航班(bfs最短路)