Acwing845 八数码

在2019年y神认为是困难题,2023年便是中等题了。。。嗯。。。

题目

在一个 3×33×3 的网格中,1∼81∼8 这 88 个数字和一个 x 恰好不重不漏地分布在这 3×33×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×33×3 的初始网格描绘出来。

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

复制代码
1 2 3 
x 4 6 
7 5 8 

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

输出格式

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

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

输入样例:

复制代码
2 3 4 1 5 x 7 6 8

输出样例

复制代码
19

代码与解析

java 复制代码
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;

public class Main {

    // BFS求解最小移动步数
    static int bfs(String state) {
        Queue<String> q = new LinkedList<>(); // 存储状态的队列
        Map<String, Integer> d = new HashMap<>(); // 记录状态及对应步数

        q.offer(state); // 初始状态入队
        d.put(state, 0); // 初始状态步数为0

        int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1}; // 上右下左四个方向

        String end = "12345678x"; // 目标状态
        while (!q.isEmpty()) {
            String t = q.poll(); // 取出队首状态

            if (t.equals(end)) return d.get(t); // 若当前状态为目标状态,则返回步数

            int distance = d.get(t); // 当前状态的步数
            int k = t.indexOf('x'); // 'x'的位置
            int x = k / 3, y = k % 3; // 'x'所在的行和列
            for (int i = 0; i < 4; i++) { // 四个方向尝试移动 'x'
                int a = x + dx[i], b = y + dy[i]; // 计算新位置的行列
                if (a >= 0 && a < 3 && b >= 0 && b < 3) { // 判断新位置是否合法
                    char[] charArray = t.toCharArray();
                    charArray[k] = charArray[a * 3 + b];
                    charArray[a * 3 + b] = 'x';
                    String newStr = String.valueOf(charArray); // 新状态

                    if (!d.containsKey(newStr)) { // 若新状态未访问过
                        d.put(newStr, distance + 1); // 记录新状态的步数
                        q.offer(newStr); // 新状态入队
                    }
                }
            }
        }

        return -1; // 无解时返回-1
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        StringBuilder state = new StringBuilder();
        for (int i = 0; i < 9; i++) {
            state.append(scanner.next()); // 读入初始状态
        }

        System.out.println(bfs(state.toString())); // 输出最小移动步数

        scanner.close();
    }
}
相关推荐
XMYX-04 小时前
Spring Boot + Prometheus 实现应用监控(基于 Actuator 和 Micrometer)
spring boot·后端·prometheus
@yanyu6665 小时前
springboot实现查询学生
java·spring boot·后端
酷爱码6 小时前
Spring Boot项目中JSON解析库的深度解析与应用实践
spring boot·后端·json
AI小智6 小时前
Google刀刃向内,开源“深度研究Agent”:Gemini 2.5 + LangGraph 打造搜索终结者!
后端
java干货7 小时前
虚拟线程与消息队列:Spring Boot 3.5 中异步架构的演进与选择
spring boot·后端·架构
一只叫煤球的猫7 小时前
MySQL 8.0 SQL优化黑科技,面试官都不一定知道!
后端·sql·mysql
写bug写bug8 小时前
如何正确地对接口进行防御式编程
java·后端·代码规范
不超限8 小时前
Asp.net core 使用EntityFrame Work
后端·asp.net
豌豆花下猫8 小时前
Python 潮流周刊#105:Dify突破10万星、2025全栈开发的最佳实践
后端·python·ai