题目正文:
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 = 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 boards 109 { 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 filename 177 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 puzzle 188 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 }