Solving the 8-Queens Problem Using Backtracking

Solving the 8-Queens Problem Using Backtracking

Verified Sources
Sep 11, 2026

The 8-Queens problem asks us to place eight chess queens on an 8×88 \times 8 chessboard so that no two queens attack one another. Because a queen attacks horizontally, vertically, and diagonally, a valid arrangement must contain no pair of queens in the same row, column, or diagonal.

The problem is a classic example of Backtracking and Constraint Satisfaction.

The generalized form is the N-Queens problem: place NN queens on an N×NN \times N board under the same restrictions. The 8-Queens problem has 92 distinct solutions, or 12 fundamental solutions when rotations and reflections are considered equivalent.

Learning objectives

By the end of this section, you should be able to:

  • State the constraints of the 8-Queens problem.
  • Explain why backtracking is appropriate.
  • Design a recursive solution.
  • Detect column and diagonal conflicts efficiently.
  • Trace an example involving placement and backtracking.
  • Analyze the algorithm’s time and space requirements.

Footnotes

  1. Eight queens puzzle - Defines the puzzle and reports 92 distinct and 12 fundamental solutions. 2

1. Modeling the Problem

A convenient representation places exactly one queen in each row. The algorithm processes rows from top to bottom and chooses a column for the queen in each row.

Let

xr=the column containing the queen in row rx_r = \text{the column containing the queen in row } r

where r{0,1,,7}r \in \{0,1,\ldots,7\} and xr{0,1,,7}x_r \in \{0,1,\ldots,7\}.

A complete solution must satisfy:

Constraint 1: Different columns

For every pair of rows r1r_1 and r2r_2:

xr1xr2x_{r_1} \ne x_{r_2}

This prevents two queens from sharing a column.

Constraint 2: Different diagonals

Two squares (r1,xr1)(r_1,x_{r_1}) and (r2,xr2)(r_2,x_{r_2}) share a diagonal when:

r1r2=xr1xr2|r_1-r_2| = |x_{r_1}-x_{r_2}|

Therefore, valid placements must satisfy:

r1r2xr1xr2|r_1-r_2| \ne |x_{r_1}-x_{r_2}|

Placing one queen per row automatically prevents row conflicts. Thus, the algorithm only needs to test columns and diagonals.

Key Modeling Insight

Place queens row by row. This guarantees that no two queens occupy the same row, reducing the problem to column and diagonal checks.

2. Why Backtracking Works

A naïve method could try every possible column assignment for eight rows. Since each row has eight choices, this produces at most

88=16,777,2168^8 = 16{,}777{,}216

possible assignments, many of which immediately violate constraints.

Backtracking improves the search by rejecting a partial arrangement as soon as it becomes impossible to complete. This is called Pruning.

The method follows a depth-first search pattern:

  1. Choose the next row.
  2. Try each column in that row.
  3. If the position is safe, place a queen.
  4. Recursively solve the remaining rows.
  5. If the recursive attempt fails, remove the queen.
  6. Try another column.

A recursive call represents a partial board configuration. For example:

[0,4,7][0,4,7]

means:

  • Row 00 has a queen in column 00.
  • Row 11 has a queen in column 44.
  • Row 22 has a queen in column 77.

The next recursive call attempts to place the queen in row 33.

Backtracking Procedure

  1. 1
    Step 1

    No queens have been placed. Begin at row 0.

  2. 2
    Step 2

    Process rows from top to bottom. Because there is one queen per row, row conflicts cannot occur.

  3. 3
    Step 3

    For the current row, examine columns from left to right.

  4. 4
    Step 4

    Reject a position if its column or either diagonal already contains a queen.

  5. 5
    Step 5

    Mark the selected column and diagonals as occupied.

  6. 6
    Step 6

    Move to the next row and repeat the same process.

  7. 7
    Step 7

    If no column is safe, remove the queen from the previous row and continue with the next available column there.

  8. 8
    Step 8

    When the algorithm reaches row 8, all eight queens have been placed safely. Store the board or column representation.

3. Efficient Safety Checking

For a queen at row rr and column cc, identify its diagonals using two indices:

  • Main diagonal: rcr-c
  • Anti-diagonal: r+cr+c

Since rcr-c can be negative, an array implementation commonly stores it using an offset of N1N-1:

mainIndex=rc+(N1)\text{mainIndex} = r-c+(N-1) antiIndex=r+c\text{antiIndex} = r+c

For an 8×88 \times 8 board:

  • Columns require 88 markers.
  • Main diagonals require 1515 markers.
  • Anti-diagonals require 1515 markers.

A position is safe exactly when:

column[c]=0\text{column}[c] = 0

and

mainDiagonal[rc+(N1)]=0\text{mainDiagonal}[r-c+(N-1)] = 0

and

antiDiagonal[r+c]=0\text{antiDiagonal}[r+c] = 0

This makes each safety check O(1)O(1) instead of scanning previously placed queens.

Footnotes

  1. N Queen Problem - Describes row-by-row backtracking, safety checks, and commonly cited complexity bounds.

Search Representation for the 8-Queens Problem

The board has 8 columns and 15 diagonals in each diagonal direction.

4. Pseudocode

The following pseudocode finds all solutions:

1procedure solve(row): 2 if row == 8: 3 record the current board 4 return 5 6 for column from 0 to 7: 7 if column is unused 8 and main diagonal is unused 9 and anti-diagonal is unused: 10 11 place queen at (row, column) 12 mark column and both diagonals as used 13 14 solve(row + 1) 15 16 remove queen from (row, column) 17 unmark column and both diagonals

The most important operation is the final cleanup:

1remove queen 2unmark column 3unmark main diagonal 4unmark anti-diagonal

Without this restoration step, later branches would incorrectly treat old trial placements as permanent.

1def solve_n_queens(n): 2 board = [["." for _ in range(n)] for _ in range(n)] 3 columns = [False] * n 4 main_diagonals = [False] * (2 * n - 1) 5 anti_diagonals = [False] * (2 * n - 1) 6 solutions = [] 7 8 def backtrack(row): 9 if row == n: 10 solutions.append( 11 ["".join(board_row) for board_row in board] 12 ) 13 return 14 15 for col in range(n): 16 main_index = row - col + (n - 1) 17 anti_index = row + col 18 19 if (columns[col] or 20 main_diagonals[main_index] or 21 anti_diagonals[anti_index]): 22 continue 23 24 board[row][col] = "Q" 25 columns[col] = True 26 main_diagonals[main_index] = True 27 anti_diagonals[anti_index] = True 28 29 backtrack(row + 1) 30 31 board[row][col] = "." 32 columns[col] = False 33 main_diagonals[main_index] = False 34 anti_diagonals[anti_index] = False 35 36 backtrack(0) 37 return solutions 38 39solutions = solve_n_queens(8) 40print(len(solutions)) 41# 92

5. Worked Example: One Successful 8-Queens Arrangement

One valid solution can be represented by the column vector:

[0,4,7,5,2,6,1,3][0,4,7,5,2,6,1,3]

This means:

RowColumnBoard row
00Q.......
14....Q...
27.......Q
35.....Q..
42..Q.....
56......Q.
61.Q......
73...Q....

The complete board is:

1Q....... 2....Q... 3.......Q 4.....Q.. 5..Q..... 6......Q. 7.Q...... 8...Q....

Verifying the arrangement

The column values are:

0,4,7,5,2,6,1,30,4,7,5,2,6,1,3

All are distinct, so no two queens share a column.

For the main diagonals, calculate rcr-c:

0,3,5,2,2,1,5,40,-3,-5,-2,2,-1,5,4

All values are distinct.

For the anti-diagonals, calculate r+cr+c:

0,5,9,8,6,11,7,100,5,9,8,6,11,7,10

All values are distinct.

Therefore, no two queens share a row, column, or diagonal.

Tracing a Backtracking Branch

  1. 1
    Step 1

    Try row 0, column 0. The partial representation is [0].

  2. 2
    Step 2

    Column 0 is blocked, and columns 1 and 2 are diagonally attacked. A later safe choice may be column 4, giving [0,4].

  3. 3
    Step 3

    The algorithm tries safe columns for rows 2, 3, and beyond. Every placement updates the column and diagonal markers.

  4. 4
    Step 4

    Suppose the current partial arrangement has no safe column for the next row. This means the current choices cannot lead to a complete solution.

  5. 5
    Step 5

    Remove the queen from the previous row and clear its three markers. This is the backtracking operation.

  6. 6
    Step 6

    Continue scanning columns in the previous row. A different choice may open a valid continuation.

  7. 7
    Step 7

    When the recursive call reaches row 8, the arrangement is a valid solution and is recorded.

6. A Smaller Trace That Clearly Shows Failure

Tracing all branches of the 8-Queens search is lengthy, so a 4-Queens branch illustrates the same mechanism more clearly.

Consider this partial placement:

1Q... 2..Q. 3.... 4....

The queens are at (0,0)(0,0) and (1,2)(1,2).

For row 22:

  • Column 00 is occupied.
  • Column 11 is attacked diagonally by the queen at (0,0)(0,0).
  • Column 22 is occupied.
  • Column 33 is attacked diagonally by the queen at (1,2)(1,2).

Therefore, row 22 has no safe position.

The algorithm backtracks:

  1. Remove the queen at (1,2)(1,2).
  2. Try another column in row 11.
  3. Continue searching from the new partial arrangement.

This demonstrates the central principle:

A failed partial arrangement is discarded immediately rather than extended further.

Common Implementation Error

Do not forget to unmark the column and both diagonals after the recursive call. Failing to restore state causes false conflicts in later branches.

7. Correctness Argument

The algorithm is correct for two reasons.

Soundness

Every recorded arrangement is valid.

  • A queen is placed only when its column is unused.
  • A queen is placed only when its main diagonal is unused.
  • A queen is placed only when its anti-diagonal is unused.
  • Exactly one queen is placed in each processed row.

Therefore, when the algorithm records a board after processing all 88 rows, no two queens attack one another.

Completeness

Every valid arrangement is eventually considered.

At each row, the algorithm tries every column that is not immediately invalid. If a partial placement can be extended to a solution, the algorithm explores that branch. If a branch cannot be extended, backtracking returns to the most recent decision and tries another possibility.

Thus, no valid arrangement is skipped. When configured to record every completed board, the algorithm finds all 92 solutions.

Footnotes

  1. Eight queens puzzle - Defines the puzzle and reports 92 distinct and 12 fundamental solutions.

8. Complexity Analysis

For the general NN-Queens problem, a common upper-bound description for straightforward backtracking is:

O(N!)O(N!)

because placing one queen per row and rejecting used columns reduces the number of possible column permutations. A less-pruned formulation can be described by the looser bound O(NN)O(N^N).

With column and diagonal arrays:

  • Safety checking: O(1)O(1) per candidate position.
  • Recursion depth: O(N)O(N).
  • Auxiliary marker space: O(N)O(N).
  • Board storage for explicit solutions: O(N2)O(N^2) per stored board.
  • Output space for all solutions: proportional to the number of solutions returned.

For N=8N=8, the search is small enough to run quickly. For larger NN, performance can be improved using bit masks, symmetry breaking, variable ordering, and constraint propagation.

Footnotes

  1. N Queen Problem - Describes row-by-row backtracking, safety checks, and commonly cited complexity bounds.

9. Important Variations

Find one solution versus all solutions

To find only one solution, return immediately after the first complete arrangement:

1if row == N: 2 return true

To find every solution, record the board and continue searching after a solution is found.

Board representation

A board can be represented as:

  • A two-dimensional array of characters.
  • A one-dimensional array where board[row] stores the column.
  • Bit masks for columns and diagonals.

The one-dimensional representation is often sufficient because the row is implied by the array index.

Symmetry reduction

Rotating or reflecting a solution produces another solution. The 8-Queens problem has 92 distinct arrangements but only 12 fundamental arrangements under these symmetries. A solver can reduce duplicate work by restricting the first queen to part of the first row and generating symmetric variants afterward.

Bit-mask optimization

For larger values of NN, occupied columns and diagonals can be encoded as bits. A bitwise operation can then identify all available positions in a row at once. This preserves the backtracking idea while reducing constant-time overhead.

Footnotes

  1. Eight queens puzzle - Defines the puzzle and reports 92 distinct and 12 fundamental solutions.

Frequently Asked Questions

8-Queens Backtracking Review

1 / 7
Question · Term

What is the goal of the 8-Queens problem?

Click to reveal
Answer · Definition

Place eight queens on an 8 × 8 board so that no two share a row, column, or diagonal.

Exam Strategy

When explaining this algorithm, always state the choice, constraint check, recursive call, base case, and undo operation. These five parts capture the complete backtracking pattern.

Knowledge Check

Question 1 of 5
Q1Single choice

Which condition identifies a diagonal conflict between queens at (r1, c1) and (r2, c2)?

Explore Related Topics

1

Semaphore and the Dining-Philosophers Solution Using Monitors

The content contrasts low‑level semaphores with high‑level monitors and shows how a monitor‑based solution avoids deadlock in the Dining Philosophers problem.

  • A semaphore offers atomic waitwait/signalsignal on a counter, but misordered calls can cause deadlock or race conditions.
  • A monitor bundles shared state with procedures and uses condition variables (x.wait()x.wait(), x.signal()x.signal()) to wait for logical predicates rather than resource counts.
  • The monitor algorithm maintains an array state[i]{THINKING,HUNGRY,EATING}state[i]\in\{THINKING, HUNGRY, EATING\} and a condition variable self[i]self[i] per philosopher; test(i)test(i) grants EATINGEATING only if both neighbors are not eating.
  • Because monitor entry is mutually exclusive and testtest is invoked on neighbours after putdown(i)putdown(i), the solution guarantees safety (no adjacent eaters) and deadlock freedom, while starvation freedom depends on fairness of signaling.
2

FIFO Branch-and-Bound Uses a Queue

FIFO Branch-and-Bound expands live nodes in the exact order they are generated, so it is implemented with a queue.

  • A queue enforces first‑in‑first‑out, giving the algorithm a BFS‑like, level‑order traversal.
  • LIFO Branch‑and‑Bound uses a stack and least‑cost Branch‑and‑Bound uses a priority queue.
  • Bounding prunes unpromising nodes independently of the FIFO selection rule.
  • Pseudocode: initialize QQ, enqueue root, while QQ\neq\emptyset dequeue front, generate children, enqueue survivors.
  • The abstract answer is “queue,” not an array or other structure, even if an array may implement a queue.
3

Designing a Turing Machine for the 2’s Complement of a Binary String