Backtracking search is a search technique used to find solutions to Constraint Satisfaction Problems (CSPs).It builds a solution by assigning values to variables one at a time and backtracks whenever an assignment violates the given constraints.
Working
Backtracking search is a depth-first search algorithm that incrementally builds a solution by trying possible assignments and abandoning (backtracking) as soon as it determines that a partial solution cannot lead to a valid final solution. Steps involved are:
- Initialization: Start with an empty assignment.
- Selection: Choose an unassigned variable.
- Assignment: Assign a value to the selected variable.
- Consistency Check: Verify whether the assignment satisfies all constraints.
- Recursion: If consistent, recursively assign values to remaining variables.
- Backtrack: If a conflict occurs or no valid continuation exists, undo the last assignment and try another value.
Implementation
We implement a backtracking search algorithm to solve a simple CSP: the N-Queens problem.
Step 1: Define the is_safe function to check whether placing a queen at board[row][col] is valid.
def is_safe(board, row, col, N):
# Check the row
for i in range(col):
if board[row][i] == 1:
return False
# Check upper-left diagonal
for i, j in zip(range(row, -1, -1), range(col, -1, -1)):
if board[i][j] == 1:
return False
# Check lower-left diagonal
for i, j in zip(range(row, N), range(col, -1, -1)):
if board[i][j] == 1:
return False
return True
Step 2: Defining the solve_n_queens function to place queens column by column using recursion and backtracking.
def solve_n_queens(board, col, N):
if col >= N:
return True
for i in range(N):
if is_safe(board, i, col, N):
board[i][col] = 1
if solve_n_queens(board, col + 1, N):
return True
board[i][col] = 0
return False
Step 3: Stating the print_board function to display the chessboard with queens placed.
def print_board(board, N):
for i in range(N):
for j in range(N):
print("Q" if board[i][j] == 1 else ".", end=" ")
print()
Step 4: Define the n_queens function to initialize the board and start the solving process.
def n_queens(N):
board = [[0] * N for _ in range(N)]
if solve_n_queens(board, 0, N):
print_board(board, N)
else:
print("No solution exists")
Step 5: Run the algorithm for N = 8 to find and display the solution.
N = 8
n_queens(N)
Output:

You can download the complete source code from here.
Optimization Techniques
- Forward Checking: After assigning a value to a variable, eliminate inconsistent values from the domains of the unassigned variables.
- Constraint Propagation: Use algorithms like AC-3 (Arc Consistency 3) to reduce the search space by enforcing constraints locally.
- Heuristics: Employ heuristics such as MRV (Minimum Remaining Values) and LCV (Least Constraining Value) to choose the next variable to assign and the next value to try.
Applications
- Scheduling Problems: Assigns tasks to time slots while satisfying constraints like deadlines, availability and dependencies
- Planning Systems: Determines valid sequences of actions to achieve a goal while ensuring all constraints are satisfied
- Resource Allocation: Distributes limited resources efficiently among competing tasks under defined constraints
- Puzzle Solving: Solves problems like Sudoku, N-Queens and crosswords where strict rules restrict valid configurations
Advantages
- Simple to implement and easy to understand, suitable for basic CSP problems.
- Effective for practical CSPs, especially when combined with heuristics and constraint propagation.
- Flexible as it can be adapted using techniques like variable ordering and forward checking.
Limitations
- It can be slow for large or highly constrained problems.
- Without optimization techniques, it may repeatedly explore invalid paths.
- It requires significant memory to store the state of the search tree.