首页 > 代码库 > 算法导论第四版学习——习题四8 Puzzle

算法导论第四版学习——习题四8 Puzzle

题目正文:

http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html

作业难点:

1、如何验证Puzzle是否可解?题目中有提示,如果相邻两个格子交换后得到的“Twin Puzzle”进行求解,如果Twin有解那么原始Puzzle就无解。

作业技巧:

1、checklist提到把Twin Puzzle和Puzzle放在一个Priority Queue中,其实就是在设计自己的Node数据结构的时候加一个boolean类型标识是否twin就好了

2、别忘了Equal的实现要素,首先是否为空、其次是否类型一致、再其次维度是否一致、最后逐个比较。

代码参考:

(这是我自己亲测100分的答案,不代表写得最好,请在自己实在完成不了的时候再看,不然的话做这个题目的意义一点都没有)

技术分享
  1 import edu.princeton.cs.algs4.In;  2 import edu.princeton.cs.algs4.StdOut;  3   4 import java.util.Stack;  5   6   7 public class Board {  8     private int ngrid;  9     private char[] board; 10     private int hammingCache; 11     private int manhattanCache; 12  13     public Board(int[][] blocks) { 14         ngrid = blocks.length; 15  16         if (ngrid < 2) { 17             throw new NullPointerException(); 18         } 19  20         board = new char[ngrid * ngrid]; 21         hammingCache = 0; 22         manhattanCache = 0; 23  24         for (int i = 0; i < ngrid; i++) { 25             for (int j = 0; j < ngrid; j++) { 26                 int currentValue =http://www.mamicode.com/ blocks[i][j]; 27                 board[(i * ngrid) + j] = (char) currentValue; 28  29                 if (currentValue != 0) { 30                     if (currentValue != ((i * ngrid) + j + 1)) { 31                         hammingCache++; 32                     } 33  34                     int col = (currentValue - 1) % ngrid; 35                     int row = (currentValue - col - 1) / ngrid; 36                     // StdOut.println("v:"+currentValue+"r:"+row+"c:"+col); 37                     manhattanCache += (((col > j) ? (col - j) : (j - col)) + 38                     ((row > i) ? (row - i) : (i - row))); 39                 } 40             } 41         } 42     } 43  44     public int dimension() // board dimension n 45      { 46         return ngrid; 47     } 48  49     public int hamming() // number of blocks out of place 50      { 51         return hammingCache; 52     } 53  54     public int manhattan() // sum of Manhattan distances between blocks and goal 55      { 56         return manhattanCache; 57     } 58  59     public boolean isGoal() // is this board the goal board? 60      { 61         return hammingCache == 0; 62     } 63  64     public Board twin() // a board that is obtained by exchanging any pair of blocks 65      { 66         int[][] twin = new int[ngrid][ngrid]; 67  68         for (int i = 0; i < ngrid; i++) { 69             for (int j = 0; j < ngrid; j++) { 70                 twin[i][j] = (int) board[(i * ngrid) + j]; 71             } 72         } 73  74         if ((twin[0][0] == 0) || (twin[0][1] == 0)) { 75             swap(twin, 1, 0, 1, 1); 76         } else { 77             swap(twin, 0, 0, 0, 1); 78         } 79  80         return new Board(twin); 81     } 82  83     public boolean equals(Object y) // does this board equal y? 84      { 85         if (y == this) { 86             return true; 87         } 88  89         if (y == null) { 90             return false; 91         } 92  93         if (y.getClass() != this.getClass()) { 94             return false; 95         } 96  97         Board that = (Board) y; 98         if (that.dimension() != ngrid) return false; 99         for (int i = 0; i < (ngrid * ngrid); i++) {100             if (this.board[i] != that.board[i]) {101                 return false;102             }103         }104 105         return true;106     }107 108     public Iterable<Board> neighbors() // all neighboring boards109      {110         int blankRow = 0;111         int blankCol = 0;112         Stack<Board> neighbours = new Stack<Board>();113 114         int[][] clone = new int[ngrid][ngrid];115 116         for (int i = 0; i < ngrid; i++) {117             for (int j = 0; j < ngrid; j++) {118                 clone[i][j] = (int) board[(i * ngrid) + j];119 120                 if (clone[i][j] == 0) {121                     blankRow = i;122                     blankCol = j;123                 }124             }125         }126 127         if (blankCol != 0) {128             swap(clone, blankRow, blankCol - 1, blankRow, blankCol);129             neighbours.push(new Board(clone));130             swap(clone, blankRow, blankCol - 1, blankRow, blankCol);131         }132 133         if (blankCol != (ngrid - 1)) {134             swap(clone, blankRow, blankCol + 1, blankRow, blankCol);135             neighbours.push(new Board(clone));136             swap(clone, blankRow, blankCol + 1, blankRow, blankCol);137         }138 139         if (blankRow != 0) {140             swap(clone, blankRow - 1, blankCol, blankRow, blankCol);141             neighbours.push(new Board(clone));142             swap(clone, blankRow - 1, blankCol, blankRow, blankCol);143         }144 145         if (blankRow != (ngrid - 1)) {146             swap(clone, blankRow + 1, blankCol, blankRow, blankCol);147             neighbours.push(new Board(clone));148         }149 150         return neighbours;151     }152 153     private void swap(int[][] array, int i, int j, int a, int b) {154         int temp = array[i][j];155         array[i][j] = array[a][b];156         array[a][b] = temp;157     }158 159     public String toString() // string representation of this board (in the output format specified below)160      {161         StringBuilder s = new StringBuilder();162         s.append(ngrid + "\n");163         for (int i = 0; i < ngrid; i++) {164             for (int j = 0; j < ngrid; j++) {165                 s.append(String.format("%2d ", (int) board[(i * ngrid) + j]));166             }167 168             s.append("\n");169         }170 171         return s.toString();172     }173 174     public static void main(String[] args) // unit tests (not graded)175      {176         // read in the board specified in the filename177         In in = new In(args[0]);178         int n = in.readInt();179         int[][] tiles = new int[n][n];180 181         for (int i = 0; i < n; i++) {182             for (int j = 0; j < n; j++) {183                 tiles[i][j] = in.readInt();184             }185         }186 187         // solve the slider puzzle188         Board initial = new Board(tiles);189         StdOut.printf("hamming:%d manhattan:%d \n", initial.hamming(),190             initial.manhattan());191         StdOut.println("dim:" + initial.dimension());192         StdOut.println(initial.toString());193         StdOut.println("goal:" + initial.isGoal());194         StdOut.println("twin:\n" + initial.twin().toString());195 196         StdOut.println("neighbours:");197 198         for (Board s : initial.neighbors()) {199             StdOut.println(s.toString());200         }201     }202 }
Board
技术分享
  1 import edu.princeton.cs.algs4.In;  2 import edu.princeton.cs.algs4.MinPQ;  3 import edu.princeton.cs.algs4.StdOut;  4   5 import java.util.Stack;  6   7   8 public class Solver {  9     private boolean solvable; 10     private GameNode originLast; 11  12     public Solver(Board initial) // find a solution to the initial board (using the A* algorithm) 13      { 14         if (initial == null) { 15             throw new NullPointerException(); 16         } 17  18         solvable = true; 19  20         MinPQ<GameNode> queue = new MinPQ<GameNode>(); 21  22         queue.insert(new GameNode(initial, null, 0, false)); 23         queue.insert(new GameNode(initial.twin(), null, 0, true)); 24  25         while (!queue.isEmpty()) { 26             GameNode processed = queue.delMin(); 27  28             if (!processed.isTwin) { 29                 originLast = processed; 30             } 31  32             if (processed.boardValue.isGoal()) { 33                 if (processed.isTwin) { 34                     solvable = false; 35                 } 36  37                 break; 38             } 39  40             for (Board neighbor : processed.boardValue.neighbors()) { 41                 if ((processed.prev == null) || 42                         !processed.prev.boardValue.equals(neighbor)) { 43                     queue.insert(new GameNode(neighbor, processed, 44                             processed.moves + 1, processed.isTwin)); 45                 } 46             } 47         } 48     } 49  50     public boolean isSolvable() // is the initial board solvable? 51      { 52         return solvable; 53     } 54  55     public int moves() // min number of moves to solve initial board; -1 if unsolvable 56      { 57         if (isSolvable()) { 58             return originLast.moves; 59         } else { 60             return -1; 61         } 62     } 63  64     public Iterable<Board> solution() // sequence of boards in a shortest solution; null if unsolvable 65      { 66         if (!isSolvable()) { 67             return null; 68         } 69  70         Stack<Board> solutions = new Stack<Board>(); 71         GameNode current = originLast; 72  73         while (current.prev != null) { 74             solutions.push(current.boardValue); 75             current = current.prev; 76         } 77  78         solutions.push(current.boardValue); 79  80         Stack<Board> solutions2 = new Stack<Board>(); 81  82         while (!solutions.empty()) { 83             solutions2.push(solutions.pop()); 84         } 85  86         return solutions2; 87     } 88  89     public static void main(String[] args) { 90         // create initial board from file 91         In in = new In(args[0]); 92         int n = in.readInt(); 93         int[][] blocks = new int[n][n]; 94  95         for (int i = 0; i < n; i++) 96             for (int j = 0; j < n; j++) 97                 blocks[i][j] = in.readInt(); 98  99         Board initial = new Board(blocks);100 101         // solve the puzzle102         Solver solver = new Solver(initial);103 104         // print solution to standard output105         if (!solver.isSolvable()) {106             StdOut.println("No solution possible");107         } else {108             StdOut.println("Minimum number of moves = " + solver.moves());109 110             for (Board board : solver.solution())111                 StdOut.println(board);112         }113     }114 115     private class GameNode implements Comparable<GameNode> {116         private Board boardValue;117         private GameNode prev;118         private int moves;119         private boolean isTwin;120 121         public GameNode(Board current, GameNode prev, int moves, boolean isTwin) {122             this.boardValue =http://www.mamicode.com/ current;123             this.prev = prev;124             this.moves = moves;125             this.isTwin = isTwin;126         }127 128         public int compareTo(GameNode that) {129             int priority1 = this.boardValue.manhattan() + this.moves;130             int priority2 = that.boardValue.manhattan() + that.moves;131 132             if (priority1 == priority2) {133                 return 0;134             } else if (priority1 > priority2) {135                 return 1;136             } else {137                 return -1;138             }139         }140     }141 }
Solver

 

算法导论第四版学习——习题四8 Puzzle