View difference between Paste ID: fa3Rt21q and
SHOW:
|
|
- or go back to the newest paste.
1 | - | |
1 | + | package edu.mit.yingyin.util; |
2 | ||
3 | import java.util.ArrayList; | |
4 | import java.util.Arrays; | |
5 | ||
6 | public class NQueens { | |
7 | ||
8 | private int size; | |
9 | private int[][] board; | |
10 | /** | |
11 | * 4 diagonal directions. | |
12 | */ | |
13 | private int[] dr = {-1, -1, 1, 1}; | |
14 | private int[] dc = {-1, 1, 1, -1}; | |
15 | private ArrayList<int[]> solutions = new ArrayList<int[]>(); | |
16 | ||
17 | public NQueens(int size) { | |
18 | this.size = size; | |
19 | board = new int[size][size]; | |
20 | for (int i = 0; i < size; i++) | |
21 | Arrays.fill(board[i], 0); | |
22 | } | |
23 | ||
24 | /** | |
25 | * An implementation that marks -1 on the board for positions that are not | |
26 | * possible after placing a queen. This is more efficient because subsequent | |
27 | * recursive calls only need to check the mark at a particular position | |
28 | * without iteration. It requires more memory however because it needs to | |
29 | * create a new copy of the board at each recursion level so that we can | |
30 | * easily undo the marking. | |
31 | * | |
32 | * @return all the solutions. | |
33 | */ | |
34 | public ArrayList<int[]> solveWithMarking() { | |
35 | solutions.clear(); | |
36 | solve1WithMarking(0, board); | |
37 | return solutions; | |
38 | } | |
39 | ||
40 | /** | |
41 | * An implementation that does not mark out invalid positions. Subsequence | |
42 | * placement of a queen needs to check conflicts iteratively. | |
43 | * | |
44 | * @return all the solutions. | |
45 | */ | |
46 | public ArrayList<int[]> solveWithoutMarking() { | |
47 | solutions.clear(); | |
48 | solve1WithoutMarking(0); | |
49 | return solutions; | |
50 | } | |
51 | ||
52 | ||
53 | public void printBoard(int[][] tmpBoard) { | |
54 | for (int r = 0; r < size; r++) { | |
55 | for (int c = 0; c < size; c++) { | |
56 | System.out.print(String.format("%+d ", tmpBoard[r][c])); | |
57 | } | |
58 | System.out.println(); | |
59 | } | |
60 | System.out.println(); | |
61 | } | |
62 | ||
63 | public int[][] getBoard() { | |
64 | return board; | |
65 | } | |
66 | ||
67 | /** | |
68 | * Solves one particular row with marking. | |
69 | * @param row | |
70 | * @param tmpBoard | |
71 | */ | |
72 | private void solve1WithMarking(int row, int[][] tmpBoard) { | |
73 | if (row == size) { | |
74 | addSolutions(tmpBoard); | |
75 | return; | |
76 | } | |
77 | ||
78 | for (int c = 0; c < size; c++) { | |
79 | if (tmpBoard[row][c] == 0) { | |
80 | int[][] newBoard = copyBoard(tmpBoard); | |
81 | markBoard(row, c, newBoard); | |
82 | solve1WithMarking(row + 1, newBoard); | |
83 | } | |
84 | } | |
85 | } | |
86 | ||
87 | /** | |
88 | * Creates a deep copy of the current temporary board. | |
89 | * @param tmpBoard | |
90 | * @return | |
91 | */ | |
92 | private int[][] copyBoard(int[][] tmpBoard) { | |
93 | int[][] newBoard = new int[size][size]; | |
94 | for (int i = 0; i < size; i++) | |
95 | System.arraycopy(tmpBoard[i], 0, newBoard[i], 0, size); | |
96 | return newBoard; | |
97 | } | |
98 | ||
99 | ||
100 | /** | |
101 | * Marks a copy of the board with -1 at positions that are in conflict with | |
102 | * position (row, col). | |
103 | * | |
104 | * @param row | |
105 | * @param col | |
106 | * @param tmpBoard | |
107 | */ | |
108 | private void markBoard(int row, int col, int[][] tmpBoard) { | |
109 | for (int i = 0; i < size; i++) { | |
110 | tmpBoard[row][i] = -1; | |
111 | tmpBoard[i][col] = -1; | |
112 | } | |
113 | for (int i = 0; i < 4; i++) { | |
114 | int nrow = row; | |
115 | int ncol = col; | |
116 | while (true) { | |
117 | nrow += dr[i]; | |
118 | ncol += dc[i]; | |
119 | if (nrow >= 0 && nrow < size && ncol >= 0 && ncol < size) | |
120 | tmpBoard[nrow][ncol] = -1; | |
121 | else break; | |
122 | } | |
123 | } | |
124 | tmpBoard[row][col] = 1; | |
125 | } | |
126 | ||
127 | private void solve1WithoutMarking(int row) { | |
128 | if (row == size) { | |
129 | addSolutions(board); | |
130 | return; | |
131 | } | |
132 | ||
133 | for (int c = 0; c < size; c++) { | |
134 | if (board[row][c] == 0 && isRowColSafe(row, c, board) && | |
135 | isDiagSafe(row, c, board)) { | |
136 | board[row][c] = 1; | |
137 | solve1WithoutMarking(row + 1); | |
138 | board[row][c] = 0; | |
139 | } | |
140 | } | |
141 | } | |
142 | ||
143 | private boolean isRowColSafe(int row, int col, int[][] b) { | |
144 | for (int i = 0; i < size; i++) { | |
145 | if (b[row][i] == 1 && i != col || b[i][col] == 1 && i != row) | |
146 | return false; | |
147 | } | |
148 | return true; | |
149 | } | |
150 | ||
151 | private boolean isDiagSafe(int row, int col, int[][] b) { | |
152 | for (int i = 0; i < 4; i++) { | |
153 | int nrow = row; | |
154 | int ncol = col; | |
155 | while (true) { | |
156 | nrow += dr[i]; | |
157 | ncol += dc[i]; | |
158 | if (nrow >= 0 && nrow < size && ncol >= 0 && ncol < size) { | |
159 | if (b[nrow][ncol] == 1) | |
160 | return false; | |
161 | } else break; | |
162 | } | |
163 | } | |
164 | return true; | |
165 | } | |
166 | ||
167 | private void addSolutions(int[][] b) { | |
168 | int[] sol = new int[size]; | |
169 | for (int r = 0; r < size; r++ ) { | |
170 | for (int c = 0; c < size; c++) { | |
171 | if (b[r][c] == 1) { | |
172 | sol[r] = c + 1; | |
173 | break; | |
174 | } | |
175 | } | |
176 | } | |
177 | solutions.add(sol); | |
178 | } | |
179 | } |