AcWing 八数码 bfs

题目链接:https://www.acwing.com/problem/content/847/
解题思路:先用str保存需要到的状态,用数组保存初始状态,将初始状态用string型入队列,拿出队头,转成二维数组方便上下左右移动,移完之后转成string入队列,每次拿出队头都与str(需要到的转态)判断,相等就直接输出,结束程序,如果通过队列为空退出的说明转不到需要的转态,输出-1.
代码如下:

#include <bits/stdc++.h>

using namespace std;
int fx[4][4]={{1,0},{0,1},{-1,0},{0,-1}};
unordered_map<string,int >m;//去掉map的排序功能,加快运行速度
int x,y;
char a[5][5];
queue<string>q;
void fun(string p){
    a[1][1]=p[0];
    a[1][2]=p[1];
    a[1][3]=p[2];
    a[2][1]=p[3];//转成数组,懒得写循环了
    a[2][2]=p[4];
    a[2][3]=p[5];
    a[3][1]=p[6];
    a[3][2]=p[7];
    a[3][3]=p[8];
    for(int i=1;i<=3;i++){
        for(int j=1;j<=3;j++){
            if(a[i][j]=='x'){
                x=i;
                y=j;//记下x的坐标,只能移他的上下左右移
                break;
            }
        }
    }
}
int main()
{
    string str="12345678x";
    string str1;
    for(int i=1;i<=3;i++){
        for(int j=1;j<=3;j++){
            cin>>a[i][j];
            str1+=a[i][j];
        }
    }
    q.push(str1);
    m[str1]=0;//初始状态需要的步数
    while(q.size()){
        string st=q.front();//拿出队头
        //cout<<st<<" ";
        if(st==str){//相等了结束程序
            cout<<m[st];
          return 0;
        }
        q.pop();
        fun(st);
        for(int i=0;i<4;i++){
            int j,k;
            j=x+fx[i][0];
            k=y+fx[i][1];
            if(j<1||k<1||j>3||k>3) continue;
            a[x][y]=a[j][k];//上下左右移
            a[j][k]='x';
            string bh="";
            for(int w=1;w<=3;w++){
                for(int r=1;r<=3;r++){
                    bh+=a[w][r];//把移完的转成字符串
                }
            }
            //cout<<bh<<endl;;
            if(m[bh]==0){//移完的字符串已经出现过了,就不需要入队列
                q.push(bh);
            }
            a[j][k]=a[x][y];
            a[x][y]='x';
            m[bh]=m[st]+1;//步数等于它上一个状态的步数加一
        }

    }
    cout<<-1;//转不到要的状态,输出-1
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

萨达大

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

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

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

打赏作者

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

抵扣说明:

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

余额充值