Acwing 179 八数码问题 (bfs or A*)

Posted hhlya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Acwing 179 八数码问题 (bfs or A*)相关的知识,希望对你有一定的参考价值。

题面

在一个3×3的网格中,1~8这8个数字和一个“X”恰好不重不漏地分布在这3×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
把“X”与上下左右方向数字交换的行动记录为“u”、“d”、“l”、“r”。

现在,给你一个初始网格,请你通过最少的移动次数,得到正确排列。

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

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

x 4 6

7 5 8

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

输出格式
输出占一行,包含一个字符串,表示得到正确排列的完整行动记录。如果答案不唯一,输出任意一种合法方案即可。

如果不存在解决方案,则输出”unsolvable”。

输入样例:
2 3 4 1 5 x 7 6 8
输出样例
ullddrurdllurdruldr

思路

直接bfs就可以了,这里由于我们需要把操作给记录下来,那么我们就需要沿着路线进行一个回溯,那么我们可能需要去保存当前状态的一个前状态和操作。用map可以解决。A*的做法的话我们需要一个有限队列并且加入估价函数,这里的估价函数就是所有乱序数字曼哈顿距离之和。

代码实现

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<unordered_map>
#include<string>
using namespace std;

char change[5]="drul";
int moves[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
string target="12345678x";

unordered_map <string, string> p2;
unordered_map <string, int > p1;

inline int bfs (string s) {
     queue <string> q;
     
     q.push (s);
     p1[s]=0;
     while (q.size ()) {
         string sh=q.front ();
         string h=sh;
         q.pop ();

         if (sh==target) return true;

         int k=sh.find (‘x‘);
         int x=k/3,y=k%3;
         for (int i=0;i<4;i++) {
             int a=x+moves[i][0];
             int b=y+moves[i][1];

             if (a>=0&&a<3&&b>=0&&b<3) {
                 int t=a*3+b;
                 swap (sh[k],sh[t]);
                 if (!p1.count (sh)) {
                     p1[sh]=i;
                     p2[sh]=h;
                     q.push (sh);
                 }
                swap (sh[t],sh[k]);
             }
         }
     }
    return false;
}



int main () {
    string s;
    char c;
    for (int i=0;i<9;i++) cin>>c, s+=c;
    
    if  (bfs (s)) {
        vector <char> arr;
        string ans=target;
        while (ans!=s) {
            arr.push_back (change[p1[ans]]);
            ans=p2[ans];
        }
        for (int i=arr.size ()-1;i>=0;i--) {
            cout<<arr[i];
        }
        cout<<endl;
    }
    else cout<<"unsolvable"<<endl;
    return 0;
}















以上是关于Acwing 179 八数码问题 (bfs or A*)的主要内容,如果未能解决你的问题,请参考以下文章

[A*] aw179. 八数码(A*+bfs最小步数模型+模板题)

AcWing 845. 八数码(BFS)

[A*] aw178. 第K短路(A*+bfs最小步数模型+好题)

AcWing 845. 八数码

八数码问题--bfs

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)