八数码问题——康托展开+A*算法

八数码问题——康托展开+A*算法康托展开节点类A星算法搜索判断0点的移动:open表的排序:估值函数:算法流程:完整代码:Search类:A星算法的实现(主要的逻辑都在这里)MyNode类:(存储每个节点的状态,以及参数的获取)Main:算法启动,获取结果链展示康托展开康托展开能够将一系列排列组合映射到有限集中,常用于构建哈希表时的空间压缩。在这里能够完成各种组合的判重。如{0,1,2,3,4}五个数字的所有排列组合,使用康托展开能够将排列组合的情况恰好转换为5!=120个整数,极大的节约空间,同时也
摘要由CSDN通过智能技术生成

康托展开

  • 康托展开能够将一系列排列组合映射到有限集中,常用于构建哈希表时的空间压缩。在这里能够完成各种组合的判重。如{0,1,2,3,4}五个数字的所有排列组合,使用康托展开能够将排列组合的情况恰好转换为5!=120个整数,极大的节约空间,同时也能够逆康托展开,求得原排列组合。
  • 在解决这里的问题能够将九个数的排列组合转换为int整数,我们直接开一个9!大小的boolean数组,若该排列组合出现过,只需要将该位置状态改为reue,这样很快地判断了是否重复。
    在这里插入图片描述在这里插入图片描述
 /**
     * 康托展开,用于判重
     * a表示全排列的数组,n位全排列
     */
    int cantor(int []a, int n) {
   
        int x = 0;
        for (int i = 0; i < n; ++i) {
   
            // 在当前位之后小于其的个数
            int smaller = 0;
            for (int j = i + 1; j < n; ++j) {
   
                if (a[j] < a[i]) {
   
                    smaller++;
                }
            }
            // 康托展开累加
            x += factorial[n - i - 1] * smaller;
        }
        return x+1;
    }

节点类

  • private int []status=new int[9]; 当前节点的九宫格排列
  • private MyNode parentNode; 当前节点的父节点
  • private int diffNum; 当前节点与目标位置不同的个数
  • private int score; 估值函数的总分,越小优先级越高
  • private int zeroPos; 0数字在状态数组中位置
  • private int depth; 当前节点遍历的层数

A星算法搜索

判断0点的移动:

使用一个9*4二维数组表示0在九宫格中的某个位置时,要交换位置在一维数组中的下标,减少了需要判断上下左右能否移动的判断,能够直接交换数字的位置,也方便遍历四个方向。

顺序为上左下右逆时针
-1表示该方向不能交换

int [][]changeId={
   {
   -1,-1,3,1},{
   -1,0,4,2},{
   -1,1,5,-1},
            {
   0,-1,6,4},{
   1,3,7,5},{
   2,4,8,-1},
            {
   3,-1,-1,7},{
   4,6,-1,8},{
   5,7,-1,-1}};
open表的排序:

这里采用了Java的PriorityQueue优先级队列,使用自定义比较器(以lambda语法简写)构造,每次从中取出的为估值最小的节点

 /**open表*/
PriorityQueue <MyNode>open=new PriorityQueue<MyNode>((o1, o2) -> o1.gethScore()-o2.gethScore());
估值函数:

采用当前节点在遍历的层数(即交换的步数)+当前节点与目标节点相差的个数,这里在节点类的构造函数中求得。

算法流程:

算法其实基于BFS广度优先算法遍历&

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值