Solving problems by breaking them into subproblems.
Make the locally optimal choice at each step.
Search through possible solutions by undoing choices.
Optimal substructure and overlapping subproblems.