BFS(宽度优先)(最短路)

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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值