-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNQueens.cpp
More file actions
261 lines (211 loc) · 5.68 KB
/
NQueens.cpp
File metadata and controls
261 lines (211 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
//============================================================================
// Name : NQueens.cpp
// Author : Imogen Cleaver-Stigum & Jyalu Wu
// Version :
// Copyright : ©2019 IMOLU
// Description :
//============================================================================
#include <iostream>
#include "NQueens.h"
using namespace std;
/*
* Runs the program for the n-Queens project. It finds the first complete
* boards for n=4 to n=20, then finds all the solutions for a particular
* n-Queens problem, for which the n is specified by the user.
*
* The boards start from index 0 instead of 1 like they do in the directions.
*/
int main() {
int n = 8;
int numSols = 0;
findCompleteBoards();
cout << "Enter in a number 4 <= n <= 20: ";
cin >> n;
numSols = findAllSolutions(n);
cout << "total number of solutions: " << numSols << endl;
return 0;
}
/*
* Returns true if no two queens attack each other in the given board.
* @param board, The given board
* @param n, The size of the board
* @return 1 if no two queens attack each other, 0 otherwise
*/
int isLegalPosition (int* board, int n) {
int isLegal = 1;
// assume there are no same-row queens since the queens are places row-by-row
for (int row = 0; row < n; row++) {
for (int j = 0; j < n; j++) { // check for same-column queens
if (board[row] == board[j] && board[row] != -1 && row != j) {
isLegal = 0;
}
}
// check for positive slope diagonal queens
for (int i = 0; i < row; i++) {
if (i + board[i] == row + board[row] && board[row] != -1 && board[i] != -1) {
return 0;
}
}
// check for negative slope diagonal queens
for (int i = 0; i < row; i++) {
if (i - board[i] == row - board[row] && board[row] != -1 && board[i] != -1) {
return 0;
}
}
}
return isLegal;
}
/*
* This function performs a backtrack for the given board.
* @param board, The given board
* @param n, The size of the board
* @param row, The last full row
* @return 1 if a legal solution was found, 0 otherwise.
*/
int backtrack (int* board, int n, int row) {
// the current row is in the last column - backtrack previous row
if (board[row] == n - 1) {
for (int i = row; i < n; i++) {
board[i] = -1;
}
if (row == 0) {
return 0;
}
return backtrack(board, n, row-1);
}
// find legal solution for the current row
for (int col = board[row]+1; col < n; col++) {
board[row] = col;
if (isLegalPosition(board, n)) {
return 1;
}
}
// reset the rest of the board after the current row
for (int i = row; i < n; i++) {
board[i] = -1;
}
return backtrack(board, n, row-1);
}
/*
* Finds the next legal position for the board by either adding a queen
* into the next empty row or by backtracking.
* @param board, The given board
* @param n, The size of the board
* @return 0 if no legal position could be found, 1 otherwise
*/
int nextLegalPosition(int* board, int n) {
int row = -1;
// find out which row was the last row filled
for (int i = 0; i < n; i++) {
if (board[i] != -1) {
row = i;
}
}
// case 1: full, legal solution
if (isLegalPosition(board, n) && row == n-1) {
return backtrack(board, n, row);
}
// case 2: partial legal solution
else if (isLegalPosition(board, n)) {
// try to add a queen to the next empty row
for (int col = 0; col < n; col++) {
board[row+1] = col;
if (isLegalPosition(board, n)) {
return 1;
}
}
// if it wasn't possible, backtrack
board[row+1] = -1;
return backtrack(board, n, row);
}
// case 3: partial illegal solution
else {
if (board[row] < n-1) {
board[row]++;
//printBoard(board, n);
if (isLegalPosition(board, n)) {
return 1;
}
else {
return nextLegalPosition(board, n);
}
}
else {
return backtrack(board, n, row);
}
}
return 0;
}
/*
* Finds the first complete board for all the n-Queens problems
* from n=4 to n=20. It becomes extremely slow after about n=22
* so please make sure that your computer does not work too hard!
*/
void findCompleteBoards () {
for (int boardSize = 4; boardSize <= 20; boardSize++) {
int* board = new int[boardSize];
for (int i = 0; i < boardSize; i++) {
board[i] = -1;
}
while (!isFull(board, boardSize)) {
nextLegalPosition(board, boardSize);
}
cout << "First complete board for n = " << boardSize << endl;
printBoard(board, boardSize);
}
}
/*
* Finds all solutions to the n-Queens Problem for a particular n and
* prints them out in lexicographical order.
* @n, The size of the board
* @return The number of solutions
*/
int findAllSolutions(int n) {
int allSolutionsFound = 0;
int numSolutions = 0;
int* board = new int[n];
for (int i = 0; i < n; i++) {
board[i] = -1;
}
while (!allSolutionsFound) {
while (!allSolutionsFound && !isFull(board, n)) {
allSolutionsFound = !nextLegalPosition(board, n);
}
if (isLegalPosition(board, n) && !allSolutionsFound) {
numSolutions++;
printBoard(board, n);
allSolutionsFound = !nextLegalPosition(board, n);
}
}
return numSolutions;
}
/*
* Checks to see whether or not the given board is full.
* @param board, The given board
* @param n, The size of the board
* @return 1 if the board is full, 0 otherwise
*/
int isFull (int* board, int n) {
int boardIsFull = 1;
for (int i = 0; i < n; i++) {
if (board[i] == -1) {
boardIsFull = 0;
}
}
return boardIsFull;
}
/*
* In the given board, for each row, the function prints out the column
* that the queen is in. If there is no queen in that column, it prints -1.
* @param board, The given board
* @param n, The size of the board
*/
void printBoard(int* board, int n) {
cout << "(";
for (int i = 0; i < n; i++) {
cout << board[i];
if (i != n-1)
cout << " " ;
}
cout << ")" << endl;
}