N Queens – Backtracking Problem 2

BackTracking:

Find a solution by trying one of several choices. If the choice proves incorrect, computation backtracks or restarts at the point of choice and tries another choice. It is often convenient to maintain choice points.

In an exhaustive search algorithm you search every possible choice to reach to the goal state, however, the backtracking algorithm is an extension, where you realize a bad choice by using some constraint and do not explore that choice any further. Hence, this is optimized by reducing the number of choices that you would explore in case of exhaustive search.

Example:

The example can help you understand the backtracking algorithm. Almost all the problems have similar structure where you have to explore various options available and the choices are in the form of tree above.

Starting at Root, your options are A and B. You choose A.
At A, your options are C and D. You choose C.
C is a bad choice and it is decided by some constraint in the real world problems. Go back to A.
At A, you have already tried option C, and it failed. Try option D.
D is bad. Go back to A.
At A, you have no options left to try. Go back to Root.
At Root, you have already tried A. Try B.
At B, your options are E and F. Try E.
E is good which is your goal. Congratulations, you have solved the backtracking problem !

Backtracking Solution Structure:

``` ALGORITHM Backtrack(X[1..i])
//Gives a template of a generic backtracking algorithm
//Input: X[1..i] specifies first i promising components of a solution
//Output: All the tuples representing the problem’s solutions
if X[1..i] is a solution write X[1..i]
else //
for each element x ∈ Si+1 consistent with X[1..i] and the constraints do
X[i + 1]←x
Backtrack(X[1..i + 1])
```

N Queens Problem:

The problem is to place n queens on an nxn chessboard so that no two
queens attack each other by being in the same row or in the same column or on
the same diagonal.

Solution:
We start with the empty board and then place queen 1 in the first possible
position of its row, which is in column 1 of row 1. Then we place queen 2, after
trying unsuccessfully columns 1 and 2, in the first acceptable position for it, which
is square (2, 3), the square in row 2 and column 3. This proves to be a dead end
because there is no acceptable position for queen 3. So, the algorithm backtracks
and puts queen 2 in the next possible position at (2, 4). Then queen 3 is placed
at (3, 2), which proves to be another dead end. The algorithm then backtracks all
the way to queen 1 and moves it to (1, 2). Queen 2 then goes to (2, 4), queen 3 to
(3, 1), and queen 4 to (4, 3), which is a solution to the problem.

```public class NQueens {

List<String[]> res = new ArrayList<String[]>();
/****number of possible solutions****/
int count=0;
public List<String[]> solveNQueens(int n) {

int A[] = new int[n];
for(int i=0; i<n; i++){
A[i]=-1;
}
solve(A,0,n);
return res;
}

public void printBoard(int[] A, int n){
String str[] = new String[n];
for(int i=0; i<n; i++){
String temp="";
for(int j=0; j<n; j++){
if(A[i]==j){
temp +="Q";
}else{
temp +=".";
}
}
str[i]=temp;
}
}

public boolean isValid(int[] A, int col){
for(int i=0; i<col; i++){
if(A[i]==A[col] || Math.abs(A[i]-A[col])== (col-i)){
return false;
}
}
return true;
}

public void solve(int[] A, int col, int n){
if(col==n){
printBoard(A,n);
count++;
}else{
for(int i=0; i<n; i++){
A[col] =i;
if(isValid(A,col)){
System.out.print(col+" ");
solve(A,col+1,n);
}
}
}
}
}
```

One Thought on “N Queens – Backtracking Problem 2”

1. #include

using namespace std;

void init_board(int C[][2], int N) {
for (int i = 1; i <= N; i++) {
C[i][0] = -1;
C[i][1] = -1;
}
}

int maxItem(int C[][2], bool isRow, int N) {
int mx = -100;
for (int i = 1; i <= N; i++) {
if (isRow) {
if (mx < C[i][0])
mx = C[i][0];
} else {
if (mx < C[i][1])
mx = C[i][1];
}
}
return mx;
}

bool collision(int l, int m, int C[][2], int N) {
for (int i = 1; i <= N; i++) {
if ((m-l) == (C[i][1]-C[i][0]))
return true;
}
return false;
}

bool findSol(int C[][2], int i, int x, int y, int N) {
int max_col = maxItem(C,false,N);
int max_row = maxItem(C,true,N);

if (max_col == -1 || max_row == -1) {
C[i][0] = 1; C[i][1] = 1;
} else {
for (int l = max_row+1; l <= N; l++)
for (int m = max_col+1; m <= N; m++) {
if (!collision(l,m,C,N) && !(l == x && m == y)) {
C[i][0] = l; C[i][1] = m;
return true;
}
}
}
return true;
}

void QueenBacktracking(int C[][2], int i, int x, int y, int N) {
if (i == N+1 || i == -1)
return;
else {
bool success = findSol(C,i,x,y,N);
if (success)
QueenBacktracking(C,i+1,C[i+1][0],C[i+1][1],N);
else
QueenBacktracking(C,i-1,C[i-1][0],C[i-1][1],N);
}
}

void PlaceNQueens(int C[][2], int N) {
init_board(C,N);
QueenBacktracking(C,1,-1,-1,N);
}

void PrintBoard(int C[][2], int N) {
for (int i = 1; i <= N; i++)
cout<<C[i][0]<<" "<<C[i][1]<<endl;
}

int main() {
int n = 10;
int C[11][2];
PlaceNQueens(C,10);
PrintBoard(C,10);

return 0;
}