This repository has been archived on 2022-06-22. You can view files and clone it, but cannot push or open issues or pull requests.
usaco-guide/content/4_Gold/DP.mdx
2020-07-18 21:36:48 -04:00

121 lines
9 KiB
Text

---
id: intro-dp
title: "Introduction to Dynamic Programming"
author: Michael Cao
prerequisites:
- complete-search
- prefix-sums
description: "Speeding up naive recursive 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", "Hard", 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", "Hard", 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", "Easy", 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", "Easy", 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", "Easy", true, ["DP", "Knapsack"], "dp[first i coins][sum] = minimum number of coins needed"),
new Problem("AC", "Knapsack 2", "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/", "Easy", 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("HR", "Edit Distance", "contests/cse-830-homework-3/challenges/edit-distance", "Easy", true, ["DP"], "dp[first i characters in first string][first j characters in second string] -> edit distance"),
new Problem("AC", "Count Paths", "https://atcoder.jp/contests/dp/tasks/dp_h", "Easy", 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 ... (nocross)", "718", "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/", "Very Easy", true, ["DP"], "dp[i] = LIS up to i, use binary search to decrease runtime from quadratic"),
new Problem("Kattis", "Longest Increasing Subsequence", "longincsubseq", "Easy", true, [], ""),
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 that appears at all levels of competition.
By breaking down the full task into sub-problems, Dynamic Programming avoids the redundant computations of brute force solutions.
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.
## Introductory Resources
Let's begin by reading some resources covering the basics of Dynamic Programming and introducing classical problems, or Dynamic Programming problems which are well known. <Asterisk> However, classical doesn't necessarily mean common. Since so many competitors know about these problems, problemsetters rarely set direct applications of them. </Asterisk>
<Resources>
<Resource source="CPH" title="7 - DP" starred>Great introduction that covers most classical problems. Mentions memoization.</Resource>
<Resource source="TC" title="DP from Novice to Advanced" url="dynamic-programming-from-novice-to-advanced">great for all skill levels</Resource>
<Resource source="CPC" title="6 - DP" url="06_dynamic_programming">examples with nonclassical problems</Resource>
<Resource source="HR" title="DP" url="https://www.hackerrank.com/topics/dynamic-programming">also covers many classical problems</Resource>
<Resource source="PAPS" title="9 - DP">starts with DAGs, which are covered in "Topological Sort"</Resource>
</Resources>
Practice makes perfect. Start by doing some 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.
<Info title="Pro Tip">
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)$).
</Info>
## Introductory USACO Problems
These are easier USACO problems which use DP, and don't require many optimizations or complex states.
<Problems problems={metadata.problems.usacoEasy} />
## Knapsack
Common variations on Knapsack, followed by more challenging problems which feature variations on the state and additional algorithms.
<Problems problems={metadata.problems.knapsack} />
## Paths in a Grid (and related)
Interesting applications of "number of paths on a grid," some of which don't directly present a grid in the problem, but can be modelled as one. <Asterisk> Such as Longest Common Subsequence. </Asterisk>
<Problems problems={metadata.problems.pathsGrid} />
## Longest Increasing Subsequence
Some of the problems in this section don't initially look like Longest Increasing Subsequence, but it ends up being the solution. <Asterisk>This can happen a lot, which is why it's a good idea to not focus on one topic unless you have a full solution</Asterisk>
<Problems problems={metadata.problems.lis} />
## Harder USACO Problems
Finish with some more challenging Dynamic Programming problems! Some of these can be very difficult, so skip around if you want.
<Problems problems={metadata.problems.usacoPast} />
## Other DP Problemsets
Dynamic Programming is a huge topic, so if you want more practice, here are some other problemsets that we found interesting.
<Resources>
<Resource source="AC" title="DP Contest" url="https://atcoder.jp/contests/dp/tasks" starred>very good!</Resource>
<Resource source="CSES" title="DP Section" url="https://cses.fi/problemset/list/" starred>also very good!</Resource>
<Resource source="CF" title="DP List" url="blog/entry/325">misc probs, a lot of which you don't need to know at this level</Resource>
</Resources>