• 845. 八数码


    在一个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
    

    现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

    输入格式

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

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

    x 4 6

    7 5 8

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

    输出格式

    输出占一行,包含一个整数,表示最少交换次数。

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

    输入样例:

    2  3  4  1  5  x  7  6  8 
    

    输出样例

    19

        #include<iostream>
        #include<queue>
        #include<algorithm>
        #include<unordered_map>
        /*
            BFS:
            俩个问题:
            1.如何用队列表示状态
            2.如何记录每个状态的距离(dist)
            
            状态表示:
            "1234x5678"展成一行用
            queue<string> 进行存储记录状态
            unordered_map<string,int>进行存储状态之间的距离dist
        
            状态转移-->将x上下左右进行移动,改变x再三成三数组的位置
            
        */
        using namespace std;
        
        int bfs(string start){
            string 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];
                
                //先判断t是不是终点,如果是终点就直接返回就好;
                if(t == end) return distance;
                
                //状态转移
                
                //寻找x的位置,返回x的下标
                int k = t.find('x');
                
                //找x的横纵坐标,将一维数组的下标转化为二维数组的下标
                int x = k/3,y = k%3;
                
                //变化上下左右与x的位置
                for(int i = 0;i < 4;i++){
                    //x y位置上下左右的数字可以用a,b表示
                    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]); //状态更新
                        
                        //如果当前t之前没有搜到过的话,就说明找到了一个新的状态
                        if(!d.count(t)){//count-->如果存在当前元素就表示1否则就表示0
                            d[t] = distance + 1;//更新状态
                            q.push(t);//将新的状态加入到队列里边去
                            
                        }
                        
                        swap(t[k],t[a*3 + b]); //状态恢复
                    }
                }
                
            }
            //宽搜如果到不了终点就返回-1
            return -1;
            
        }
        
        int main(){
            string start;
            
            for(int i = 0;i < 9;i++){
                char c;
                cin >> c;
                start += c;
            }
            
            cout << bfs(start) << endl;
            return 0;
            
        }
    

      

  • 相关阅读:
    車(rook)
    那些年,我们学过的文化课
    皇后(queen)
    蚂蚁运输(ant)
    [Z]CS权威会议
    [Z] 北大一牛人生物转申CS的经历
    TLS协议扫盲(握手,非对称加密,证书,电子签名等)
    关于SSE的一些资料
    Java下LDAP操作的资料
    [Z] Windbg以及vs debug使用
  • 原文地址:https://www.cnblogs.com/luyuan-chen/p/11689779.html
Copyright © 2020-2023  润新知