BFS AcWing 845 八数码

BFS AcWing 845 八数码

题目描述

在一个 \(3×3\) 的网格中,\(1 \sim 8\)\(8\) 个数字和一个 x 恰好不重不漏地分布在这 \(3 \times 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 \times 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

思路

BFS算法的经典板子题。

注意以下几点:

  1. 输入的一维字符串要进行一维转二维的操作才能利用方向数组。
  2. 二维运算后必须再转一维字符串加入队列。
  3. 注意边界条件。
  4. unordered_map进行去重,如果重复就剪枝。

代码

#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;

int bfs(string start)
{
    // 存储各次字符情况的状态图,string类型
    queue<string> q;

    // 存储变换到相应状态图所需的最小步数
    unordered_map<string, int> d;

    // 初始化队列
    q.push(start);
    d[start] = 0;// 初始步数为0

    string END = "12345678x";
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};

    // 队列
    while (q.size()){
    // 获取当前状态
    string t = q.front();
    q.pop();

    int dist = d[t];// 在哈希表里查找状态图t的最小步数
    if (t == END) return dist;// 如果已经成为最后要求的状态,则返回步数

    // 状态转移
    int k = t.find('x');// 找到x的位置
    int x = k / 3, y = k % 3;// 一维转二维

    for (int i = 0; i < 4; i++){
        int a = x + dx[i], b = y + dy[i];// 在3*3方格中上下左右遍历

        if (a >= 0 && a < 3 && b >= 0 && b < 3){

            swap(t[k], t[a * 3 + b]);// 注意这里要把二维转一维

            // 如果x和数交换后出现了新的状态图
            if (!d.count(t)){// 即在d中找键值t为空
                d[t] = dist + 1;// t的最小步数更新为dist+1
                q.push(t);// 把t入队,保证队列中所有状态图不会相同
            }

            swap(t[k], t[a * 3 + b]);// 注意,新的图t如果入队过了,就必须把刚交换的状态图调整回来

        }
    }
    }

    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;
}
posted @ 2025-02-19 16:44  AKgrid  阅读(17)  评论(0)    收藏  举报