8 puzzle问题

    8-puzzle问题是cousera上algorithm的第四周作业。

    8-puzzle问题如上所示,用A*算法求从一个乱序的数字拼图(initial board)到顺序(goal board)数字拼图的最短路径,每次移动只能通过将空白块与数字块交换来实现。

    感觉cousera上作业的specification已经将A*算法讲的很清楚了,主要是有些需要注意的地方,如果不知道的话很难得到满分。

    这题的A*算法的大概思路为:

 1.将initial放入一个优先级队列中(优先级是队列中元素与goal的曼哈顿距离以及initial移动到队列中元素的距离);

2.若队列不为空,从优先级队列中取出优先级最高的board;

3.判断2中取出的board,是否是goal board,是的话则得到了最终的goal board,可以找出最短路径,得到结果;否则转4;

4.找出这个board的neighbour(即移动一次得到的所有board),放入优先级队列中),转2;

但这样子就有个问题,3中从优先级队列中取出了优先级最高的元素之后,如何反推得到移动路线和移动次数。单纯用Board类无法做到,就得新建一个类searchnode,类中存放着board和board的移动次数以及board的前一个board(这样的话通过这个就可以反推最短路径),因此这个优先级队列应该是searchnode的优先级队列,而不是Board的。

又因为不是每一个initial board都是可以移动得到goal board(有解)的,如何检测呢,作业说明中介绍了这样一个结论:如果一个initial board有解,那么它的twin board(交换任意两个相邻非空白元素得到的board)则无解;如果initial无解,twin board就有解;

因此只要改进以下A*算法的实现思路,将initial和一个twin都放入同一个优先级队列,最后一定可以得到一个goal,检查goal的源头到底是initial还是twin即可判断initial是否有解。

作业需要实现两个类。

Borad类的实现没啥大问题,需要注意的是equals的实现完整性,判断是否为空,为自己,类是否相同以及toString的实现要按照课程的格式。

Solver类的实现需要注意的有:

1,将一些需要多次调用的函数,提前用实例变量存储下来,比如求的曼哈顿距离,优先级;

2.提前判断,避免重复计算的情况,这里主要是指一个board的prev和neighbour相同的情况(剔除走回头路的情况)。

 

满分的代码如下:

Board.java:

/******************************************************************************
 *  NetID:   lark
 *  CreatedTime: 2020/2/18 17:09.
 *
 *  Description:  Board.java
 ******************************************************************************/
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;

import java.util.Iterator;


public class Board {
    private int[][] tiles;
    private int n;
    private final int hamming;
    public Board(int[][] tiles)
    {
        n = tiles.length;
        this.tiles = new int[n][n];
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                this.tiles[i][j] = tiles[i][j];
            }
        }
        int ham = 0;
        for (int i = 0; i < n; i
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值