题目正文:

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 }
Board

相关文章: