Dynamic programming is an algorithmic technique that breaks down optimization problems into subproblems. It solves subproblems only once and stores the results for future use, unlike divide-and-conquer which solves subproblems independently. Examples where dynamic programming can be applied include the knapsack problem, Fibonacci numbers, shortest paths, and project scheduling. The 0-1 knapsack problem involves selecting items with weights and values to maximize the total value within a weight limit, where each item is either fully included or not.