This document discusses dynamic programming and greedy algorithms. It begins by defining dynamic programming as a technique for solving problems with overlapping subproblems. It provides examples of dynamic programming approaches to computing Fibonacci numbers, binomial coefficients, the knapsack problem, and other problems. It also discusses greedy algorithms and provides examples of their application to problems like the change-making problem, minimum spanning trees, and single-source shortest paths.