Write the recursive solution first, then add a cache so each state is computed only once. Same power as bottom-up DP, often easier to think about.
What Is It?
Dynamic programming solves problems by breaking them into overlapping subproblems. Top-down (memoization) is the most natural way to write it: you define a recursive function dp(state) that returns the best answer for that state, and you cache results so each state is computed at most once.
Without the cache, the recursion recomputes the same states exponentially. With it, each state is solved once and looked up for free afterward. This is the difference between O(2^n) and O(n*k) (or whatever the state space is).