Starting from a (DFS-like) recursive algorithm that searches the entire state space, we (a) memoize it [increasing efficiency, at the cost of memory], then (b) make a bottom-up memoized version, and finally (c) realize we can reduce the memory-usage of this bottom-up version = a "dynamic programming" version.