Backtracking Algorithm
The Backtracking Algorithm is a general algorithmic technique used to solve optimization and combinatorial problems. It is often used to find all (or some) solutions to problems that involve exploring a large search space, such as puzzles, constraint satisfaction problems, and combinatorial search.
Backtracking is typically used when the problem requires exploring different possibilities or configurations and rejecting configurations that do not meet the problem's criteria. It's often described as a depth-first search where the algorithm "backtracks" when it reaches a state that cannot lead to a solution.
Backtracking systematically searches for a solution by exploring all possible options and undoing (or "backtracking") when it determines that a certain path will not lead to a solution.
The algorithm can be described as follows:
A classic example of a backtracking problem is the N-Queens Problem, where the goal is to place N queens on an N×N chessboard such that no two queens threaten each other.
def is_safe(board, row, col, n):
# Check the column
for i in range(row):
if board[i] == col or abs(board[i] - col) == row - i:
return False
return True
def solve_n_queens(board, row, n):
# If all queens are placed, return True
if row == n:
return True
for col in range(n):
if is_safe(board, row, col, n):
board[row] = col # Place the queen
if solve_n_queens(board, row + 1, n): # Recurse to place the next queen
return True
board[row] = -1 # Backtrack
return False
def print_solution(board):
for i in range(len(board)):
row = ['.'] * len(board)
row[board[i]] = 'Q'
print(' '.join(row))
def n_queens(n):
board = [-1] * n # Initialize the board with -1
if solve_n_queens(board, 0, n):
print_solution(board)
else:
print("No solution exists")
# Example: Solve 4-Queens problem
n_queens(4)
#include <iostream>
#include <vector>
using namespace std;
bool is_safe(const vector<int>& board, int row, int col) {
for (int i = 0; i < row; i++) {
// Check if the queen can be attacked by another queen
if (board[i] == col || abs(board[i] - col) == row - i)
return false;
}
return true;
}
bool solve_n_queens(vector<int>& board, int row, int n) {
if (row == n) // All queens are placed
return true;
for (int col = 0; col < n; col++) {
if (is_safe(board, row, col)) {
board[row] = col;
if (solve_n_queens(board, row + 1, n))
return true;
board[row] = -1; // Backtrack
}
}
return false;
}
void print_solution(const vector<int>& board) {
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board.size(); j++) {
if (board[i] == j) cout << "Q ";
else cout << ". ";
}
cout << endl;
}
}
void n_queens(int n) {
vector<int> board(n, -1); // Initialize the board
if (solve_n_queens(board, 0, n)) {
print_solution(board);
} else {
cout << "No solution exists" << endl;
}
}
int main() {
n_queens(4); // Solve 4-Queens problem
return 0;
}
Time Complexity:
In the worst case, backtracking has a time complexity of O(b^d), where b is the branching factor (the number of choices at each step) and d is the depth of the recursion (the number of steps taken before reaching a solution). In the case of the N-Queens problem, this would be O(N!) since there are N! possible arrangements of queens.
Space Complexity:
The space complexity is generally O(d) due to the recursion stack, where d is the depth of the recursion.
Combinatorial Problems:
Puzzle Solving:
Constraint Satisfaction Problems (CSP):
Optimization Problems:
Artificial Intelligence (AI):