zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    javascript、CSS、XML动太生成树菜单
    设表格细钱
    JS操作JSON总结
    Meta标签详解
    js中eval详解
    搜虎网上线
    Fluent NHibernate demo 示例
    Oracle 索引概述
    程序员如何加薪——请看《谁赚走了你的薪水_让经济学帮你加薪].(英)蒂姆·哈福德.扫描版[ED2000.COM].pdf》
    expertoracledatabasearchitectureoracledatabaseprogramming9i10gand11gtechniquesandsoluti.pdf
  • 原文地址:https://www.cnblogs.com/hhlya/p/13363937.html
Copyright © 2011-2022 走看看