普林斯顿大学算法第一部分学习总结(Week4-Priority Queue)

第四周的作业是解决8-Puzzle的问题,该问题是使用Priority Queue的一个实例。原文地址http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html

模型描述:

在九宫格里,有从1-8两两互不相等的整数,加上一个空格(用0表示)。我们需要每次将空格和四周的一个格子交换位置,最后形成从(0,0)到(2,1)为1-8顺序的九宫格。类似于华容道游戏,区别在于华容道每个格子有大小。

 
  
8 1 3 8 1 3 8 1 8 1 3 8 1 3 4 2 4 2 4 2 3 4 2 4 2 5 7 6 5 7 6 5 7 6 5 7 6 5 7 6 previous search node neighbor neighbor neighbor (disallow)

如图所示,从左到右显示出每步的步骤,最后完成目标。

解决方法如下:

首先给出如下定义:Board:每次形成的九宫格,

Neighbour:能够从给定Board只移动一个格子一次就达到的新Board,

Previous:该Board从由之前的哪个Board变换而来,

需要做的事:

1.首先构造Board类,该类具有如下API

public class Board {
    public Board(int[][] blocks)           // construct a board from an N-by-N array of blocks
                                           // (where blocks[i][j] = block in row i, column j)
    public int dimension()                 // board dimension N
    public int hamming()                   // number of blocks out of place
    public int manhattan()                 // sum of Manhattan distances between blocks and goal
    public boolean isGoal()                // is this board the goal board?
    public Board twin()                    // a board that is obtained by exchanging any pair of blocks
    public boolean equals(Object y)        // does this board equal y?
    public Iterable neighbors()     // all neighboring boards
    public String toString()               // string representation of this board (in the output format specified below)

}
2.构造Solver类,

public class Solver {
    public Solver(Board initial)           // find a solution to the initial board (using the A* algorithm)
    public boolean isSolvable()            // is the initial board solvable?
    public int moves()                     // min number of moves to solve initial board; -1 if unsolvable
    public Iterable solution()      // sequence of boards in a shortest solution; null if unsolvable
    public static void main(String[] args) // solve a slider puzzle (given below)
}

实现:

用MinPriorityQueue实现A*算法,MinPQ和课堂上讲的不一样,课堂上讲的MaxPQ包含删除Max,找到Max的方法。MinPQ类似,首先将初始的Board插入MinPQ,然后删除min,既是该初始Board,然后插入min的邻居到MinPQ里面,再在新的删除min,再插入min的邻居,最后直到min就等于Goal。


该例子应用PQ,PQ的作用比较简单,就是能够快速提取出min或者max的已经sortted的数组。

构建的时候使用Binary Heap,将大的元素排在father。如果给出一个PQ,使用Heapsort就能对它进行排序。



实行起来分工明确,比较简单,但是需要很多注意的地方:

1.当我们在构造两个不同的对象需要用到同一个参数时,要对该参数构造aux,然后用aux进行。

eg, 给定一个数组test,现在需要构造两个Board,其中一个是Board b1 = new Board(test); 第二个是Borad b2 = new Board(test)。

但是如果在b1里面进行操作,比如b1.blocks[0][0] = 0, 那么同样在b2里面的也会变化。原因是b1.blocks是个reference, 指向的是test,更改b1.blocks的时候,其实就是在改动test,而b2又是利用test构造的对象,所以b2也会发生变化。要正确使用,在构造b1的时候就需要aux,

int[][] aux = test; Board b1 = new Board(test);

此时如果再对b1.blocks 进行更改,就不会对test产生影响,再用

Board b2 = new Board(test)构造的b2就是一个没有被b1影响的新Board;


2.在进行数组比较的时候,不能直接使用  a[] == b[]的符号,一维数组使用Array.equals(a[], b[]). 二维数组需要自己写for for 循环比较;


3.在把某个对象转化成String输出时,可以使用

StringBuilder s = new StringBuilder()

s.append(N+"\n"); 既是加入N和换行,

s.append(String.format("%2d", blocks[i][j]));既是加上将int转换为String格式的字符。


4.找二维数组某个特定值x的坐标可以用如下方法:(需要用两个break来跳出for循环)

int blankI = 0, blankJ = 0;

    for (int i = 0; i < N; i++) {

for (int j = 0; j < N; j++) {

if (blocks[i][j] == x) {

blankI = i;

blankJ = j;

break;

}

}

if (blocks[blankI][blankJ] == 0) break;

  }


5.当对于某个对象的一个方法能产生很多其他对象的时候,可以选择return Iterable> 的方法。

public Iterable<Board> neighbors()

比如上述,只需要新建一个Queue,然后把产生的neighbors全都放入Queue里面,再返回这个Queue。之后就能使用foreach将neighbors方法产生的所有neighbor都遍历出来;

你可能感兴趣的:(算法自学)