Backtracking & Branch-and-Bound
Backtracking ও Branch and Bound
1. Backtracking = DFS + Pruning
Backtracking explores a tree of partial solutions. The template:
- Choose the next decision.
- Explore (recurse).
- Un-choose (backtrack to previous state).
Without pruning, backtracking is naive brute force and explodes exponentially. With pruning, many practical NP-hard problems become solvable for moderate sizes.
2. N-Queens — The Classic
Place N queens on N × N so none attack each other. Place row by row; for each row, try each column — prune if column / diagonal already used.
#include <bits/stdc++.h>
using namespace std;
int N = 8, count_ = 0;
vector<bool> col, d1, d2;
void solve(int r) {
if (r == N) { count_++; return; }
for (int c = 0; c < N; c++) {
if (col[c] || d1[r + c] || d2[r - c + N]) continue;
col[c] = d1[r + c] = d2[r - c + N] = true;
solve(r + 1);
col[c] = d1[r + c] = d2[r - c + N] = false;
}
}
int main() {
col.assign(N, false);
d1.assign(2*N, false);
d2.assign(2*N, false);
solve(0);
cout << "N=" << N << " solutions = " << count_; // 92 for N=8
}
3. Generate All Permutations
#include <bits/stdc++.h>
using namespace std;
vector<int> cur;
vector<bool> used;
void go(vector<int>& a) {
if (cur.size() == a.size()) {
for (int x : cur) cout << x << " ";
cout << "\n"; return;
}
for (int i = 0; i < (int)a.size(); i++) {
if (used[i]) continue;
used[i] = true; cur.push_back(a[i]);
go(a);
cur.pop_back(); used[i] = false;
}
}
int main() {
vector<int> a = {1, 2, 3};
used.assign(a.size(), false);
go(a);
}
4. Branch and Bound — Pruning by Bounds
Branch-and-bound adds a numeric bound on the best achievable from a partial state. If the bound can't beat the current best, prune the entire branch. Common in 0/1 knapsack, TSP, integer programming.
5. Iterative Deepening DFS
DFS with a depth limit, increasing the limit by 1 until a solution is found. Combines DFS's low memory with BFS's optimal-depth guarantee. Used in IDA* for puzzles, in iterative-deepening alpha-beta for chess engines.
6. Practice Problems
-
Generate all subsets (power set) of {1, 2, 3}.Power set।
✨ Show Answer (উত্তর দেখুন)
Approach: for each index i, recurse twice — once with a[i] included, once without. 2ⁿ leaves.
-
Combination sum — find all combinations summing to target (each number can be reused).Combination sum (reuse allowed)।
✨ Show Answer (উত্তর দেখুন)
Approach: sort. DFS with starting index. From current index, either include current (recurse with same start) or skip to next (start = i+1).
-
Word break II — return all valid sentence segmentations of a string given a dictionary.Word break II।
✨ Show Answer (উত্তর দেখুন)
Approach: backtracking + DP cache. For each starting index, try every split point; if prefix is in dictionary, recurse on suffix.
-
Restore IP addresses — split a digit string into 4 parts each in 0..255.IP address restore।
✨ Show Answer (উত্তর দেখুন)
Approach: recurse with parts placed so far; try lengths 1, 2, 3 for each part; prune leading zeros and out-of-range.
-
Rat in a maze — print all paths from (0,0) to (n−1,n−1).Rat in a maze।
✨ Show Answer (উত্তর দেখুন)
Approach: DFS with visited matrix. Move U/D/L/R; on each, mark visited, recurse, then un-mark.
-
Palindrome partitioning — list every way to split a string into palindromic pieces.Palindrome partitioning।
✨ Show Answer (উত্তর দেখুন)
Approach: at each starting index, try every prefix; if it is a palindrome, recurse on the rest.
-
Sudoku solver — backtracking with row/col/box constraints.Sudoku solver।
✨ Show Answer (উত্তর দেখুন)
a7.cpp#include <bits/stdc++.h> using namespace std; int g[9][9]; bool r[9][10], c[9][10], b[9][10]; bool solve(int i, int j) { if (i == 9) return true; int ni = j == 8 ? i+1 : i, nj = (j+1)%9; if (g[i][j]) return solve(ni, nj); int bi = (i/3)*3 + j/3; for (int v = 1; v <= 9; v++) if (!r[i][v] && !c[j][v] && !b[bi][v]) { g[i][j] = v; r[i][v] = c[j][v] = b[bi][v] = true; if (solve(ni, nj)) return true; g[i][j] = 0; r[i][v] = c[j][v] = b[bi][v] = false; } return false; } int main() { // fill g[][] with puzzle (0 = blank), set r/c/b, then solve(0,0). cout << "sudoku solver template"; }
Summary — Module 37
Backtracking is DFS with pruning — the choose/explore/un-choose pattern. Branch and bound adds numeric pruning bounds. Iterative deepening combines DFS memory with BFS optimality. Sudoku, N-queens, permutations, and many "list every X" problems all use this template.