八数码问题dfs

news/2025/2/22 12:41:17

 

java">


import java.util.*;

public class Main{
    static String end = "12345678x";
    public static void swap(char[] arr,int x,int y){
        char temp = arr[x];
        arr[x] = arr[y];
        arr[y] = temp;
    }

    public static int bfs(String start){
        //key:String 存放12345678x这种格式的字符
        //value:int 存放start - key 这个状态需要多少步
        //最终的map.get(end)就是答案
        Map<String,Integer> map = new HashMap<>();
        //里面放12345678x这种格式的字符
        Queue<String> q = new LinkedList<>();

        //开始宽搜
        //先把头节点放入队列
        q.offer(start);
        //初始化头节点
        //根据上面的定义 start -> start所需的步数为0
        map.put(start,0);

        //用将字符串转成3 * 3的数组,用偏移量来表示哪些点可以走(可以交换)(可以走到x这个位置)
        int[] dx = {-1,0,1,0}, dy = {0,1,0,-1};

        while (!q.isEmpty()){
            //只要队列不空,就把队头拿出来,并把队头可以扩展的点放入
            String t = q.poll();

            if (t.equals(end)) return map.get(t);

            //然后对t做文章(扩展)
            //t是12345678x格式的字符,要找到x的下标,对应到3 * 3的矩阵,去找可以上下左右扩展的点
            int k = t.indexOf('x');

            int x = k / 3;
            int y = k % 3;

            for (int i = 0; i < 4; i++) {
                int a = x + dx[i];
                int b = y + dy[i];
                //将满足条件的点(没被用过且再矩阵內部)加入队列,更新map
                if (a >= 0 && b >= 0 && a < 3 && b < 3){
                    //将满足条件的点()加入队列,更新map
                    //拿到下一个点的状态,看看这个状态是否已经被遍历过了
                    char[] arr = t.toCharArray();
                    swap(arr,k,a * 3 + b);
                    //此时的arr数组就是下一个可以走的点
                    //将arr转成字符串
                    String str = new String(arr);
                    if (map.get(str) == null){
                        //该点第一次遍历,更新map里的点并且把它放入队列
                        map.put(str,map.get(t) + 1);
                        q.offer(str);
                    }
                    //因为这里操作的是arr数组,并没有操作t,恢复现场可有可无
                }
            }
        }
        return -1;
    }

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String start = "";
        for (int i = 0; i < 9; i++) {
            String s = sc.next();
            start += s;
        }
        System.out.println(bfs(start));
    }
}


http://www.niftyadmin.cn/n/5357728.html

相关文章

VS2022S使用C语言获取系统时间、C4996编译器报错

获取系统时间&#xff1a; #include <stdio.h> #include <string.h> #include <time.h>void getlocaltime() {time_t nowtime;struct tm timeinfo;time(&nowtime);localtime_s(&timeinfo, &nowtime);int year, month, day, hour, min, sec;year …

微服务—Docker

目录 初识Docker Docker与虚拟机的区别 镜像与容器 Docker架构 常见Docker命令 镜像命令 容器命令 数据卷挂载 直接挂载 初识Docker 在项目部署的过程中&#xff0c;如果出现大型项目组件较多&#xff0c;运行环境也较为复杂的情况&#xff0c;部署时会碰到一些问题&…

elementUI实现selecttree自定义下拉框树形组件支持多选和搜索

elementUI实现selecttree自定义下拉框树形组件支持多选和搜索 效果图定义子组件父组件应用 效果图 定义子组件 主要结合el-select和el-tree两个组件改造的。 <template><div class"selectTree"><el-select filterable :filter-method"filterMe…

【MySQL】学习并使用聚合函数和DQL进行分组查询

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-t8K8tl6eNwqdFmcD {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

如何发布自己的npm包:

1.创建一个打包组件或者库&#xff1a; 安装weback&#xff1a; 打开项目&#xff1a; 创建webpack.config.js,创建src目录 打包好了后发现两个js文件都被压缩了&#xff0c;我们想开发使用未压缩&#xff0c;生产使用压缩文件。 erserPlugin&#xff1a;&#xff08;推荐使用…

Codeforces Round 922 (Div. 2)(A~D)补题

A题考虑贪心&#xff0c;要使使用的砖头越多&#xff0c;每块转的k应尽可能小&#xff0c;最小取2&#xff0c;最后可能多出来&#xff0c;多出来的就是最后一块k3&#xff0c;我们一行内用到的砖头就是 m 2 \frac{m}{2} 2m​下取整&#xff0c;然后乘以行数就是答案。 #inclu…

【HTML】自定义属性(data)

自定义属性 data: 的用法&#xff08;如何设置,如何获取) &#xff0c;有何优势&#xff1f; data-* 的值的获取和设置&#xff0c;2种方法: 传统方法 getAttribute() 获取 data- 属性值; setAttribute() 设置 data- 属性值getAttribute() 获取 data- 属性值; setAttribute()…

软件工程知识梳理2-需求分析

需求分析时软件定义的最后一个阶段&#xff0c;它的基本任务时准确回答系统必须做什么的问题。 输出&#xff1a;本阶段必须的输出时软件需求规格说明书。 角色&#xff1a;需求分析员 参与者&#xff1a;用户、需求分析员 需求分析遵循的准则&#xff1a; 必须理解并描述问…