---
id: dp
title: "Introduction to Dynamic Programming"
author: Michael Cao
prerequisites:
- Recursion
- Silver - Prefix Sums
description: Speeding up naive solutions with memoization.
frequency: 4
---
import { Problem } from "../models";
export const metadata = {
problems: {
usacoEasy: [
new Problem("Gold", "Hoof Paper Scissors", "694", "Easy", false, ["DP"], "dp[first i games][# changes][last gesture] -> max games won"),
new Problem("Gold", "Time is Mooney", "993", "Easy", true, ["DP", "Graphs"], "dp[time][city] -> money"),
new Problem("Gold", "Teamwork", "863", "Easy", false, ["DP"], "let dp[i] -> max sum of skill levels for the first i cows, then precompute subarray maximums"),
new Problem("Gold", "Snakes", "945", "Easy", false, ["DP"], "dp[i][j] -> minimum sum of net sizes needed to catch m snakes with k changes, precompute maximums"),
],
usacoPast: [
new Problem("Gold", "Circular Barn Revisited", "622", "Normal", true, ["DP", "Brute Force"], "brute force starting location, then do dp[first i positions][number of doors used][position of last door] -> minimum distance cows need to travel"),
new Problem("Gold", "Taming the Herd", "815", "Normal", false, ["DP"], "dp[consider first i entries only][last breakout in first i occurs at j][k breakouts among first i entries] -> # changes"),
new Problem("Gold", "Moortal Cowmbat", "971", "Normal", true, ["DP", "Prefix Sums", "All Pairs Shortest Path"], "dp[first i letters form valid combo][last letter] -> time, Floyd Warshall on alphabet, then use prefix sums to speed up transitions."),
new Problem("Plat", "Team Building", "673", "Normal", false, [], ""),
new Problem("Gold", "Stamp Painting", "791", "Hard", false, ["DP"], "must be K consectutive of same color, complimetary counting for dp[up to position i][number of consecutive] -> number of ways, find closed form to reduce runtime"),
],
knapsack: [
new Problem("CSES", "Unordered Coin Change", "1635", "Intro", true, ["DP", "Knapsack"], "dp[first i coins][sum] = number of ways, order of loops is capacity then coins, remember to take MOD after every computation"),
new Problem("CSES", "Ordered Coin Change", "1636", "Intro", true, ["DP", "Knapsack"], "dp[first i coins][sum] = number of ways, order of loops is coins then capacity, remember to take MOD after every computation"),
new Problem("CSES", "Minimum Coins", "1634", "Intro", true, ["DP", "Knapsack"], "dp[first i coins][sum] = minimum number of coins needed"),
new Problem("Atcoder", "Knapsack 2", "https://atcoder.jp/contests/dp/tasks/dp_e", "Easy", false, ["DP", "Knapsack"], "maximum capacity is large, and sum of values is small, so switch the states. dp[first i items][sum of values] = minimum capacity needed to achieve this sum"),
new Problem("Gold", "Fruit Feast", "574", "Easy", false, ["DP", "Knapsack"], "dp[fullness] = whether you can achieve this fullness"),
new Problem("Gold", "Talent Show", "839", "Hard", false, ["DP", "Knapsack", "Binary Search", "Math"], "binary search on optimal ratio, then do knapsack on weight"),
new Problem("CF", "Round Subset", "http://codeforces.com/contest/837/problem/D", "Normal", false, ["DP", "Knapsack"], "dp[i][j][l] -> maximum amount of twos we can collect by checking first i numbers, taking j of them with total power of five equal to l"),
],
pathsGrid: [
new Problem("LC", "Longest Common Subsequence", "https://leetcode.com/problems/longest-common-subsequence/", "Intro", true, ["DP"], "dp[first i characters in first string][first j characters in second string] -> longest common subsequence, transition if s[i] = t[j] for strings s and t"),
new Problem("HackerRank", "Edit Distance", "https://www.hackerrank.com/contests/cse-830-homework-3/challenges/edit-distance", "Intro", true, ["DP"], "dp[first i characters in first string][first j characters in second string] -> edit distance"),
new Problem("Atcoder", "Count Paths", "https://atcoder.jp/contests/dp/tasks/dp_h", "Intro", true, ["DP"], "dp[x][y] = number of paths up to the point (x,y) in grid"),
new Problem("Gold", "Cow Checklist", "670", "Easy", false, ["DP"], "dp[visited i Hs][visited j Gs][last cow visited on left/right] -> min energy"),
new Problem("Gold", "Radio Contact", "598", "Easy", false, ["DP"], "dp[up to ith step of Farmer John][up to jth step of bessie] = minimum distance"),
new Problem("Gold", "Why Did The Cow Cross the Road II", "598", "Normal", false, ["DP"], "dp[up to ith field on left side][up to jth field on right side] = maximum number of disjoint crosswalks"),
new Problem("Old Gold", "Palindromic Paths", "553", "Hard", false, ["DP"], "start from the middle, dp[row i][row j][length] = number of strings of length 2 * length + 1 with ends at row i and j"),
],
lis: [
new Problem("LC", "Longest Increasing Subsequence", "https://leetcode.com/problems/longest-increasing-subsequence/", "Intro", true, ["DP"], "dp[i] = LIS up to i, use binary search to decrease runtime from quadratic"),
new Problem("Old Gold", "Cowjog", "496", "Easy", false, ["DP"], "direct application of longest increasing subsequence"),
new Problem("Plat", "Sort It Out", "865", "Very Hard", false, ["DP"], "component of kth largest LIS, read editorial for more details"),
],
}
}
Dynamic Programming is an important algorithmic technique in competitive programming which extends to even the International Olympiad of Informatics. By storing results to overlapping subproblems, Dynamic Programming optimizes the redundant computation of naive recursive solutions, massively improving computational complexity. Although it is not too difficult to grasp the general ideas behind Dynamic Programming, or DP, the technique can be used in a diverse range of problems and is a must-know idea for competitors in the USACO gold division.
(what's memoization? what's a good DP example?)
## Tutorial
The following tutorials serve as an introduction into the mindset of DP.
great introduction that covers most classical problems
great for all skill levels
examples with nonclassical problems
also covers many classical problems
starts with DAGs, which are covered in "Topological Sort"
Practice makes perfect. Start by doing some classical problems (try at least one of each), as these are **must know** DP problems. Each topic starts with direct applications of the classical problems, and then some interesting variations and USACO problems which utilize the ideas. Solutions for most problems (excluding USACO) can be found on Chapter 7 of CPH.
Sometimes it's a good idea to write a slower polynomial-time solution and then optimize it to the desired complexity (say, write $O(N^2)$ first and then speed it up to $O(N)$).
## Introductory USACO Problems
## Knapsack
## Paths in a Grid (and related)
## Longest Increasing Subsequence
## Harder USACO Problems
## Other DP Problemsets
DP is a very important topic, so you should do a lot of practice on it.
very good!
also very good!
misc probs, a lot of which you don't need to know at this level