普林斯顿算法课第四周作业

来源:互联网 发布:监控淘宝均价软件 编辑:程序博客网 时间:2024/05/23 19:40

8 Puzzle

作业地址:http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html

----------------------------------------------------------------------------------------------------------
第四周作业 8 Puzzle
8 puzzle 是一个经典的拼图问题
将九宫格内乱序的8个数字按顺序整理好,一次只能移动一个数字到空位当中。


作业中提供的思路是Best-first search(最好优先搜索)
首先定义一个Search Node,记录初始到达当前状态的移动次数和上一个状态。
通过不断从优先级队列中取出Search Node 去寻找下一级的状态,并在其中找到最符合优先级的结果。
而要确定优先级就要使用以下两个方法:
Hamming priority function:表示不在目标位置的数目
Manhattan priority function:所有方块距离目标位置之和。

然后是需要注意的几个问题:
1.A critical optimization


防止重复状态的出现,需要进行判断


2.Game Tree  将状态以搜索树的方式储存,每一个节点对应一个状态。在每一步中,用A*算法
删除优先级队列中权值最小的那个节点。


3.Detecting infeasible puzzles 
有一些初始状态是不可能得到目的状态的。题目中给我们的方法是,将同行的两个数进行交换,
如果其中一个得到目标解,那么另外一个则不可能。


最后有一些方法可能使用不当,很多都超时了
代码如下:
Board.java
import java.util.Arrays;import java.util.Comparator;public class Board {private final int[][] blocks;private final int N;// construct a board from an N-by-N array of blocks// (where blocks[i][j] = block in row i, column j)    public Board(int[][] blocks){    N = blocks.length;    this.blocks = new int[N][];    for (int i=0; i<N; i++){    this.blocks[i] = Arrays.copyOf(blocks[i], N);    }        }        // board dimension N    public int dimension(){    return this.N;    }        // number of blocks out of place    public int hamming(){    int i_hamming = 0;    for (int i=0; i<N; i++){    for (int j=0; j<N && i+j < 2*N - 2; j++){    if (blocks[i][j] != i*N + j + 1){        i_hamming++;    }    }    }    return i_hamming;    }        // sum of Manhattan distances between blocks and goal    public int manhattan(){    int i_manhattan = 0;    for (int i=0; i<N; i++){    for (int j=0; j<N; j++){    if (blocks[i][j] != 0){    i_manhattan += Math.abs((blocks[i][j] - 1) % N - j) + Math.abs((blocks[i][j] - 1) / N - i);    }    }    }    return i_manhattan;    }        // is this board the goal board?    public boolean isGoal(){    return this.hamming() == 0;    }        // a board obtained by exchanging two adjacent blocks in the same row    public Board twin(){    int[][] twinBoard = new int[N][N];for (int i=0; i<N; i++){for (int j=0; j<N; j++){twinBoard[i][j] = blocks[i][j];}}    if (blocks[0][0] != 0 && blocks[0][1] != 0){    int temp = twinBoard[0][0];    twinBoard[0][0] = twinBoard[0][1];    twinBoard[0][1] = temp;    }else{    int temp = twinBoard[1][0];    twinBoard[1][0] = twinBoard[1][1];    twinBoard[1][1] = temp;    }    return new Board(twinBoard);    }        // does this board equal y?    public boolean equals(Object y){    if (y == this) return true;        if (y == null) return false;        if (y.getClass() != this.getClass()){    return false;    }        Board thatBoard = (Board)y;    if (this.N != thatBoard.N){    return false;    }        int[][] arr_thatBoard = thatBoard.blocks;    for (int i=0; i<N; i++){    for (int j=0; j<N; j++){    if (blocks[i][j] != arr_thatBoard[i][j]){    return false;    }    }    }    return true;    }        // all neighboring boards    public Iterable<Board> neighbors(){    int blank_i = N;    int blank_j = N;    for (int i=0; i<N; i++){    for (int j=0; j<N; j++){    if (blocks[i][j] == 0){    //this is where the blank is    blank_i = i;    blank_j = j;    }    }    }    MinPQ<Board> q = new MinPQ<Board>(new Comparator<Board>() {            public int compare(Board o1, Board o2) {                if (o1.manhattan() < o2.manhattan()) return -1;               else if (o1.manhattan() == o2.manhattan()) return 0;               else return 1;            }        });    if (blank_j - 1 >= 0){    int[][] arr_temp = getCopy();    arr_temp[blank_i][blank_j] = arr_temp[blank_i][blank_j - 1];    arr_temp[blank_i][blank_j - 1] = 0;    q.insert(new Board(arr_temp));//    arr_temp = blocks.clone();    }    if (blank_j + 1 < N){    int[][] arr_temp = getCopy();    arr_temp[blank_i][blank_j] = arr_temp[blank_i][blank_j + 1];    arr_temp[blank_i][blank_j + 1] = 0;    q.insert(new Board(arr_temp));//    arr_temp = blocks.clone();    }    if (blank_i - 1 >= 0){    int[][] arr_temp = getCopy();    arr_temp[blank_i][blank_j] = arr_temp[blank_i - 1][blank_j];    arr_temp[blank_i - 1][blank_j] = 0;    q.insert(new Board(arr_temp));//    arr_temp = blocks.clone();    }    if (blank_i + 1 < N){    int[][] arr_temp = getCopy();    arr_temp[blank_i][blank_j] = arr_temp[blank_i + 1][blank_j];    arr_temp[blank_i + 1][blank_j] = 0;    q.insert(new Board(arr_temp));//    arr_temp = blocks.clone();    }    return q;    }        // string representation of the board (in the output format specified below)    public String toString() {        StringBuilder s = new StringBuilder();        s.append(N + "\n");        for (int i = 0; i < N; i++) {            for (int j = 0; j < N; j++) {                s.append(String.format("%2d ", blocks[i][j]));            }            s.append("\n");        }        return s.toString();    }        private int[][] getCopy(){    int[][] result = new int[N][];    for (int i=0; i<N; i++){    result[i] = Arrays.copyOf(blocks[i], N);    }    return result;    }        public static void main(String[] args) {        // create initial board from file        In in = new In(args[0]);        int N = in.readInt();        int[][] blocks = new int[N][N];        for (int i = 0; i < N; i++)            for (int j = 0; j < N; j++)                blocks[i][j] = in.readInt();        Board initial = new Board(blocks);        StdOut.println(initial);        StdOut.println(initial.hamming());    }}


Solver.java
import java.util.Comparator;public class Solver {private boolean isSolve = false;private int move = -1;private class SearchNode implements Comparable<SearchNode>{private final Board board;private final int move;private final int priority;private final SearchNode parent;private final boolean isTwin;public SearchNode(Board board, int move, SearchNode parent, boolean isTwin){this.board = board;this.move = move;this.priority = board.manhattan() + move;this.parent = parent;this.isTwin = isTwin;}@Overridepublic int compareTo(SearchNode that) {if (this.board.equals(that.board)) return 0;if (this.priority < that.priority) return -1;else return 1;}}private MinPQ<SearchNode> minPQ = new MinPQ<SearchNode>(new Comparator<SearchNode>() {        public int compare(SearchNode o1, SearchNode o2) {            if (o1.priority < o2.priority) return -1;           else if (o1.priority == o2.priority) return 0;           else return 1;        }    });private Stack<Board> solutionQueue = new Stack<Board>();// find a solution to the initial board (using the A* algorithm)    public Solver(Board initial){    Board initialTwin = initial.twin();    SearchNode initSearchNode = new SearchNode(initial, 0, null, false);    SearchNode initSearchNodeTwin = new SearchNode(initialTwin, 0, null, true);    minPQ.insert(initSearchNode);    minPQ.insert(initSearchNodeTwin);    solve();    }        private void solve(){    while(true){    //solve for original        SearchNode searchNode = minPQ.delMin();        if (searchNode.board.isGoal()){        if (searchNode.isTwin){        this.isSolve = false;        this.move = -1;        } else {        this.isSolve = true;            this.move = searchNode.move;            this.solutionQueue.push(searchNode.board);            while(searchNode.parent != null){            searchNode = searchNode.parent;            this.solutionQueue.push(searchNode.board);            }        }        break;        }else{        for (Board neiborBoard: searchNode.board.neighbors()){        SearchNode neiborNode = new SearchNode(neiborBoard, searchNode.move+1, searchNode, searchNode.isTwin);        if (searchNode.parent == null){        minPQ.insert(neiborNode);        } else if (!searchNode.parent.board.equals(neiborNode.board)){        minPQ.insert(neiborNode);        }        }        }    }    }        // is the initial board solvable?    public boolean isSolvable(){    return this.isSolve;    }        // min number of moves to solve initial board; -1 if no solution    public int moves(){    return this.move;    }        // sequence of boards in a shortest solution; null if no solution    public Iterable<Board> solution(){    if (this.isSolve){    return this.solutionQueue;    }else{    return null;    }        }        public static void main(String[] args) {        // create initial board from file        In in = new In(args[0]);        int N = in.readInt();        int[][] blocks = new int[N][N];        for (int i = 0; i < N; i++)            for (int j = 0; j < N; j++)                blocks[i][j] = in.readInt();        Board initial = new Board(blocks);        // solve the puzzle        Solver solver = new Solver(initial);        // print solution to standard output        if (!solver.isSolvable())            StdOut.println("No solution possible");        else {            StdOut.println("Minimum number of moves = " + solver.moves());            for (Board board : solver.solution())                StdOut.println(board);        }    }}







0 0
原创粉丝点击