蓝桥杯历届试题——九宫重排(双向BFS)

1.题目描述

在这里插入图片描述

2.输入输出及样例

在这里插入图片描述

3.解题思路

采用双向BFS,在刚开始传入参数时,将初态的dirmat设置为1,终态的dirmat设置为2。
cntmat代表的是矩阵x累计所花费的步数。
dirmat代表的是矩阵x的BFS方向(1代表正向,2代表反向)
进入while循环后,不断的取队首元素,并在四个方向进行nextmat。
对每一次nextmat的结果进行判断,如果下一个矩阵可行并且在当前方向上没有被访问过,则进入下一个判断:若正向与逆向相遇,则直接返回答案。否则,sucmat矩阵入队,同时该矩阵的dirmat方向被赋予当前方向的值,并且它的cntmat值加1。若直到队列为空都不相遇,即没有解,返回-1。
答案步数=正向BFS次数+逆向BFS次数+1

4.源代码

#include<bits/stdc++.h>
using namespace std;

int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};
string nextMat(string mat, int dir){
    int dotInd = mat.find('.');
    int sucX = dotInd/3 + dx[dir], sucY = dotInd%3 + dy[dir];
    if(sucX<0|| sucY<0|| sucX>2|| sucY>2) return "null";
    swap(mat[dotInd], mat[(sucX*3)+sucY]);
    return mat;
}
int BFS(string start, string end){
    queue<string> queMat;
    queMat.push(start), queMat.push(end);
    map<string, int> cntMat, dirMat;
    cntMat[start] = 0, cntMat[end] = 0;
    dirMat[start] = 1, dirMat[end] = 2;//正向为1,逆向为2。 
    while(!queMat.empty()){//BFS循环结束的条件是直到队列为空 
        string curMat = queMat.front();
        queMat.pop();
        for(int i=0; i<4; i++){
            string sucMat = nextMat(curMat, i);
            if(sucMat != "null"&& dirMat[sucMat] != dirMat[curMat]){ //矩阵sucMat可行 且 矩阵sucMat在该方向上未被访过。
                if(dirMat[curMat] + dirMat[sucMat] == 3) return cntMat[curMat] + cntMat[sucMat] + 1;//该状态下,正向BFS和逆向BFS相遇,返回步数 
                queMat.push(sucMat);
                dirMat[sucMat] = dirMat[curMat];//在当前方向上(正向或逆向)上标注状态,正向为1,逆向为2. 
                cntMat[sucMat] = cntMat[curMat] + 1;//将统计值+1后赋给下一个矩阵 
            }
        }
    }
    return -1;//如果是死局,则返回-1 
}
int main(){
    string a, b;
    cin>>a>>b;
    cout<<BFS(a, b);
    return 0;
}

5.总结

这是一道双向BFS的题,同时在两个方向上使用BFS,直到状态相遇,这样写的好处是可以优化程序性能,降低BFS所带来的时间复杂度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chase__young

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值