BFS实现方式
BFS通过队列来实现的
搜索过程如下:
BFS模版:
while(队列不空)
{
队头插入;
向四个方向走
判断是否符合条件;
若符合
更新距离
插入队尾
}
AcWing 844. 走迷宫
思路:
//BFS宽度优先搜索
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
int g[N][N], d[N][N];
PII q[N * N];//queue
int n, m;
int bfs()
{
int hh = 0, tt = 0;
q[0] = {0, 0};//队头为起点
memset(d, -1, sizeof d);//距离初始化为-1
d[0][0] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};//偏移量,及方向数组
while (hh <= tt)
{
auto t = q[hh ++];//记录下来这个点并且将队头弹出
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;
q[++ tt] = {x, y};//队尾加入该点
}
}
}
return d[n - 1][m - 1];
}
int main()
{
scanf("%d%d", &n, &m );
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++)
scanf("%d", &g[i][j] );
cout << bfs() << endl;
}
Acwing 845.八数码
难点:状态表示比较难,此题中是用字符串来表示状态,核心思想还是宽搜即BFS
//BFS(宽搜)
//用字符串存储状态
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <unordered_map>
using namespace std;
const int N = 10;
int bfs(string start)
{
string end;
end = "12345678x";//最后需要到达的串
queue<string> q;//队列
unordered_map<string, int> d;//距离
q.push(start);//向队列中放入起点
d[start] = 0;//起始距离为0
int dx[4] = { 1, 0, -1, 0}, dy[4] = { 0, 1, 0, -1};//偏移量,方向数组
while (q.size())//当队列中存在元素
{
auto t = q.front();//记录下队头元素的字符串类型
q.pop();//队头弹出
int distance = d[t];//记录距离,即交换的次数
if (t == end) return distance;
//状态转移
int k = t.find('x');//找到字符串中x所对应的下标
int x = k / 3, y = k % 3;//变成矩阵中的坐标
for (int i = 0; i < 4; i ++ )//四个方向依次遍历
{
int a = x + dx[i], b = y + dy[i];//存储交换字母的坐标
if (a >= 0 && a < 3 && b >= 0 && b < 3)//在边界以内
{
swap(t[k], t[a * 3 + b]);//交换字母
if (!d.count(t))//当前交换后字符串之前没有搜过
{
d[t] = distance + 1;
q.push(t);
}
swap(t[k], t[a * 3 + b]);//恢复现场
}
}
}
return -1;//没有找到
}
int main()
{
string start;
char c;
for (int i = 0; i < 9; i ++ )
{
cin >> c;
start += c;
}
cout << bfs(start) << endl;
return 0;
}