7.13

From The Algorithm Design Manual Solution Wiki
Jump to navigation Jump to search

Idea. After each throw you may pick any value 1–6, then—if the square reached is the mouth of a chute or the foot of a ladder—you are forced to its other end. Hence a move is a directed edge     i → g(i+k)  for every k∈{1…6}, where g(x) returns the square at the bottom/top of a chute/ladder whose entry is x (or x itself if none). With all edges having equal cost (1 throw) the problem is the single-source shortest-path problem on an unweighted graph; breadth-first search (BFS) yields the answer in O(n) time and O(n) space. Pseudocode (0-based squares for brevity, so finish is n-1):

function min_throws(n, jump): # jump[i] = destination of chute/ladder starting at i, or i dist = array(n, ∞) dist[0] = 0 Q = queue() Q.push(0) while not Q.empty(): v = Q.pop() if v == n-1: return dist[v] # reached last cell for k in 1..6: w = v + k if w < n: w = jump[w] # forced ride on chute/ladder if dist[w] == ∞: dist[w] = dist[v] + 1 Q.push(w) return -1 # unreachable (never happens in a legal board)
Explanation. 1. Pre-compute jump in O(n). 2. BFS scans each square once and inspects up to 6 edges, so total time O(6n)=O(n); the queue and distance array need O(n) memory. 3. When the exit square n-1 is popped, its distance is the minimal number of throws because BFS explores states in increasing throw count. Optional Python snippet (straightforward translation):
from collections import deque def min_throws(n, chutes_ladders): jump = list(range(n)) for a, b in chutes_ladders: # pairs (mouth/base, destination) jump[a-1] = b-1 # convert to 0-based inf = n+1 dist = [inf]*n dist[0] = 0 q = deque([0]) while q: v = q.popleft() if v == n-1: return dist[v] for k in range(1,7): w = v+k if w < n: w = jump[w] if dist[w] == inf: dist[w] = dist[v]+1 q.append(w) return -1
This algorithm outputs the minimum possible number of rigged dice throws required to reach square n.


Back to Chapter 7