Dynamic programming is a technique for solving problems with overlapping subproblems and optimal substructure. It works by breaking problems down into smaller subproblems and storing the results in a table to avoid recomputing them. Examples where it can be applied include the knapsack problem, longest common subsequence, and computing Fibonacci numbers efficiently through bottom-up iteration rather than top-down recursion. The technique involves setting up recurrences relating larger instances to smaller ones, solving the smallest instances, and building up the full solution using the stored results.