Preamble

N-Queens is classic constraint satisfaction: place N queens on an N×N board so no two share a row, column, or diagonal. Eight and nine differ only in search width—the pattern is DFS + pruning (backtracking).


State representation

Rows are placed one at a time; store column index per row. Conflicts check columns in O(1) with a set, and diagonals via r - c and r + c families—also O(1) membership with sets.

def n_queens(n):
    # Each solution: length-n list — index = row, value = column.
    out = []

    def backtrack(row, cols, diag, anti, board):
        if row == n:
            out.append(board[:])
            return
        for c in range(n):
            d1, d2 = row - c, row + c
            if c in cols or d1 in diag or d2 in anti:
                continue
            cols.add(c)
            diag.add(d1)
            anti.add(d2)
            board.append(c)
            backtrack(row + 1, cols, diag, anti, board)
            board.pop()
            cols.remove(c)
            diag.remove(d1)
            anti.remove(d2)

    backtrack(0, set(), set(), set(), [])
    return out

Pruning beats brute force

Clarity beats micro-optimizations until N forces bitmask tricks. The lesson generalizes: search with cheap rejection wins naive enumeration.


Conclusion

Backtracking is DFS with undo. Dijkstra’s Algorithm with heapq in Python implements Dijkstra with heapq.