Phase 19 - Lesson 19.10

Search: Backtracking, Branch-and-Bound, Binary Search, Meet-in-the-Middle

How to explore an exponential space without visiting all of it - plus the computational geometry predicates that let you prune in the plane.

⏱ 70 min● Advanced🔗 Prereqs: 19.7 DP; 19.8 bitmasks; 19.9 graphs
↖ Phase 19 hub
Builds on: 19.8 compressed the state; here we avoid visiting most states at all.
Leads to: 19.14 turns pruning into a feasibility estimate. The Euler Lab’s Search & Geometry problems (magic squares, Sudoku-like puzzles, lattice/triangle geometry) live here.

Learning Objectives

Click a status chip to cycle: Not started → In progress → Studied → Practiced → Needs review → Mastered.

Key Vocabulary

Backtracking
DFS over partial solutions; extend, test feasibility, and undo. The gain comes entirely from failing FAST.
Pruning / constraint propagation
Discarding a partial solution the moment it cannot be completed. Reduces the effective branching factor, not the worst-case exponent.
Branch-and-bound
Backtracking + an admissible bound on the best completion; prune any branch whose bound is worse than the incumbent.
Binary search on the answer
When \(P(x)\) is monotone in \(x\), find the threshold in \(O(\log\text{range})\) evaluations. Also called parametric search.
Meet in the middle
Split the input in half, enumerate both halves (\(2^{n/2}\) each), and join by sorting/hashing. Turns \(2^n\) into \(2^{n/2}\log\).
Orientation predicate
The sign of the cross product \((b-a)\times(c-a)\): +, 0 or − for counter-clockwise, collinear, clockwise. Exact in integer arithmetic.
Shoelace formula
The area of a polygon from its vertices: \(2A=\big|\sum_i (x_iy_{i+1}-x_{i+1}y_i)\big|\) - integer-exact for lattice polygons.

Intuition & Motivation

Intuition
Every search technique here answers the same question: how do I avoid looking at most of the space? Backtracking prunes branches that cannot be completed; branch-and-bound prunes branches that cannot be optimal; binary search exploits monotonicity to discard half the space per probe; meet-in-the-middle halves the exponent by paying memory. None of them changes the worst case - they change the case you actually meet.

Backtracking and pruning

The template: maintain a partial assignment; at each level, try every legal extension; recurse; undo. The only lever is the legality test - the earlier you can prove that a partial solution is doomed, the more of the tree disappears.

Worked Example - N-queens: from \(8^8\) to a few thousand nodes
1
Naive: place a queen anywhere on each of the 8 rows → \(8^8=16{,}777{,}216\) placements to test.
2
Prune 1 - one queen per column: only permutations survive, \(8!=40{,}320\).
3
Prune 2 - check diagonals as you place: a partial placement of \(k\) queens that already has a conflict is abandoned immediately, so entire subtrees never open.
4
The diagonal test is \(|r_i-r_j|=|c_i-c_j|\), which we track incrementally with three sets: used columns, used \(r+c\) (anti-diagonals), used \(r-c\) (diagonals). Each test is \(O(1)\).
5
Result: the search visits roughly 2 000 nodes and finds all 92 solutions for \(n=8\) instantly. The exponent did not change - the constant and the branching factor did.
6
Same three sets, stored as bitmasks (19.8), give the classic branch-free N-queens: free = ~(cols | diag1 | diag2) & full, then iterate the set bits with free & -free.

Branch-and-bound

Definition - Admissible bound
A function \(B(\text{partial})\) that is a valid optimistic estimate: for a minimisation problem, \(B(\pi)\le\) the true cost of every completion of \(\pi\). If \(B(\pi)\ge\) the incumbent best, no completion of \(\pi\) can beat the incumbent, so the whole subtree is discarded.

The admissibility requirement is what makes pruning safe: because the bound never overestimates, discarding a branch can never discard an optimum. A tighter bound prunes more but costs more to compute - the design trade-off is entirely about that balance. (This is the same optimism condition as the \(h\) heuristic in A*.)

Binary search on the answer

Theorem - Parametric search
Let \(P:\{L,\dots,R\}\to\{\text{false},\text{true}\}\) be monotone (once true, always true). Then the least \(x\) with \(P(x)\) true can be found with \(\lceil\log_2(R-L+1)\rceil\) evaluations of \(P\), by maintaining the invariant \(P(\text{lo}-1)=\text{false},\ P(\text{hi})=\text{true}\).

The art is inventing the predicate. ‘What is the minimum capacity that allows the shipment in \(D\) days?’ is hard; ‘does capacity \(c\) suffice?’ is easy and monotone. Turning an optimisation into a decision problem, then bisecting, is one of the highest-yield moves in competitive mathematics.

Meet in the middle

\[2^{n}\ \longrightarrow\ 2\cdot 2^{n/2}\ \text{enumeration} \;+\; O\!\big(2^{n/2}\log 2^{n/2}\big)\ \text{join}\;=\;O\!\big(2^{n/2}\,n\big).\] (19.20)

For \(n=40\): \(2^{40}\approx1.1\times10^{12}\) becomes \(2\times2^{20}\approx2\times10^6\) enumerations plus a sort. The price is \(O(2^{n/2})\) memory. It applies whenever the objective decomposes additively across the two halves - subset sums, \(x^a+y^b=T\) searches, 4-sum, and discrete-log baby-step/giant-step.

Computational geometry: exact predicates, then prune

Geometric search (lattice triangles, convex hulls, point location) is search plus a handful of predicates. Compute them in integers (19.4) - the sign of a determinant is a discrete fact and must never be decided by a float.

\[\operatorname{orient}(a,b,c)=\begin{vmatrix} b_x-a_x & c_x-a_x\\ b_y-a_y & c_y-a_y\end{vmatrix}=(b_x-a_x)(c_y-a_y)-(b_y-a_y)(c_x-a_x).\] (19.21)

Its sign is +1 if \(a\to b\to c\) turns counter-clockwise, 0 if collinear, −1 if clockwise. From it you get, with no divisions and no floats:

Coding workbench

The Euler Lab’s Search & Geometry problems reward exactly this instinct: before enumerating, ask whether the space can be halved (binary search), split (meet-in-the-middle), or pruned (backtracking with a bound). And in the geometry problems - lattice triangles containing the origin, right-triangle counts, convex-hull questions - the winning move is always an integer predicate, never a float.

Common Mistakes to Avoid
  • Backtracking without incremental feasibility checks: testing a full assignment at the leaves throws away the entire benefit.
  • Using a bound that is not admissible (it overestimates the best completion). You will prune the optimum and never know.
  • Binary-searching a non-monotone predicate. Bisection is only valid on a monotone (or unimodal, for ternary search) landscape.
  • Meet-in-the-middle without enough memory: \(2^{n/2}\) for \(n=50\) is 33 million entries - check the memory before the clock.
  • Deciding geometric predicates with floats. orient returning 1e-17 instead of 0 makes three collinear points a triangle and silently corrupts a convex hull.
Quant Practitioner Tips
  • Order your branching by the most constrained variable first (fewest legal values). This one heuristic often beats a cleverer algorithm.
  • Turn optimisation into decision, then bisect. ‘Minimise X’ is hard; ‘is X ≤ c achievable?’ is often easy and monotone.
  • Meet-in-the-middle is the standard rescue when \(n\approx40\): too big for \(2^n\), too small for a polynomial algorithm to exist.
  • Keep all lattice geometry in integers; multiply through by denominators rather than dividing. Twice the area is an integer - use \(2A\) as your quantity and never divide.

Practice this in the Euler Lab

Computational problems that exercise exactly this technique. Each opens in the Euler Lab with a Python workbench, a progressive hint ladder, and answer checking. Tier A/B run at full scale in the browser.

Warm-up:
#6 Sum Square Difference (1%, tier A) #9 Special Pythagorean Triplet (1%, tier A) #28 Number Spiral Diagonals (2%, tier A) #39 Integer Right Triangles (2%, tier A)

Applied:
#293 Pseudo-Fortunate Numbers (16%, tier B) #504 Square on the Inside (16%, tier B) #265 Binary Circles (17%, tier B)

Challenge:
#147 Rectangles in Cross-hatched Grids (41%, tier C) #161 Triominoes (41%, tier C)

322 Project Euler problems in total are mapped to this lesson. Open the Euler Lab to filter them all.

Knowledge Check

Q1 Medium
Branch-and-bound is guaranteed to find the optimum only if the bound is:
Tight
Admissible (never worse than the best possible completion)
Fast to compute
Monotone
Q2 Medium
Meet-in-the-middle solves a 40-element subset-sum in about:
\(2^{40}\approx10^{12}\) operations
\(2\cdot2^{20}\approx2\times10^6\) enumerations plus a sort
\(40^2=1600\) operations
Polynomial time
Q3 Medium
Why compute the orientation predicate in exact integers?
It is faster
Because its SIGN is a discrete decision; a float rounding of a near-zero determinant flips collinear to non-collinear and corrupts everything downstream
Because floats cannot multiply
To save memory

Practical Exercise

(a) You must find the smallest side length \(s\) such that a certain packing fits. Testing a given \(s\) costs \(O(n\log n)\) and is monotone. Give the total cost of finding \(s\) to integer precision in \([1,10^9]\). (b) Count how many lattice triangles with vertices among \(\{0,\dots,3\}^2\) contain the origin strictly inside - describe the exact-integer algorithm (do not enumerate by hand). (c) Use Pick’s theorem to find the number of interior lattice points of the triangle \((0,0),(6,0),(0,9)\).

▶ Show full solution

(a) Binary search on the answer: the predicate ‘does side \(s\) fit?’ is monotone (if \(s\) fits, so does anything larger), so bisection over \([1,10^9]\) needs \(\lceil\log_2 10^9\rceil=30\) evaluations. Total \(O(30\cdot n\log n)\) - i.e. 30 times the cost of a single feasibility check. The optimisation is no harder than the decision, up to a log factor.

(b) Enumerate all \(\binom{16}{3}=560\) triples of the 16 lattice points. For each, compute the three orientations \(\operatorname{orient}(a,b,O),\ \operatorname{orient}(b,c,O),\ \operatorname{orient}(c,a,O)\) by (19.21) in exact integers. The origin is strictly inside iff all three signs are equal and none is zero (a zero means the origin lies on an edge line). Degenerate (collinear) triples are excluded automatically because their own orientation is 0. Cost: \(O(\binom{16}{3})\) with 3 integer determinants each - trivially fast and exactly correct. (For the record, with the origin as a corner of this grid no triangle can contain it strictly inside; the algorithm is what matters, and it is the one you would run on a million random triples.)

(c) Vertices \((0,0),(6,0),(0,9)\). Area by shoelace: \(2A=|0\cdot0-6\cdot0 + 6\cdot9-0\cdot0 + 0\cdot0-0\cdot9|=54\), so \(A=27\). Boundary points: each edge contributes \(\gcd(|\Delta x|,|\Delta y|)\) - \(\gcd(6,0)=6\), \(\gcd(6,9)=3\), \(\gcd(0,9)=9\) - so \(B=6+3+9=18\). Pick: \(A=I+\tfrac B2-1\Rightarrow 27=I+9-1\Rightarrow I=19\). Nineteen interior lattice points - obtained with two gcds and one integer determinant, no floating point anywhere.

After the reveal, answer for yourself: Part (c) used 19.1 (gcd), 19.4 (exact integers) and a geometric identity in three lines. Which other lessons in this phase would you expect to combine this readily?

Lesson Summary

Search techniques all attack the same enemy: an exponential space you must not fully visit. Backtracking prunes infeasible partials (N-queens drops from \(8^8\) to thousands of nodes); branch-and-bound prunes suboptimal ones, and is correct exactly when the bound is admissible; binary search on the answer converts optimisation into a monotone decision and costs \(O(\log)\) probes; meet-in-the-middle halves the exponent to \(O(2^{n/2}n)\) by paying memory. Geometric search rests on exact integer predicates - the orientation determinant, the shoelace area, and Pick’s theorem.

Retrieval Practice

Close the lesson and answer from memory before checking. This is deliberate, effortful recall - the single highest-yield study action.

▶ Show retrieval prompts & answers
Q: What property must a branch-and-bound bound have, and why?
A: Admissibility: it must never be worse (for minimisation, never larger) than the true best completion. Then a branch whose bound already loses to the incumbent cannot contain the optimum, so pruning it is safe.
Q: Meet-in-the-middle: cost, and the condition to apply it.
A: \(O(2^{n/2}n)\) time, \(O(2^{n/2})\) memory. It requires the objective to decompose ADDITIVELY across the two halves, so that half-results can be joined by sorting/hashing.

Completion Checklist

Confidence / mastery rating
Personal notes

Source References

This lesson synthesizes and paraphrases concepts from the sources below. No copyrighted text, problem sets, or solutions are reproduced. Return to the originals for full depth.