Range DP
Authors: Michael Cao, Andi Qu
Solving a DP problem on every contiguous subarray of the original array.
Prerequisites
Tutorial
Dynamic programming on ranges is a general technique used to solve problems of the form "what is the minimum/maximum metric one can achieve on an array ?" with the following properties:
- A greedy approach seems feasible but yields incorrect answers.
- Given the answers for each subarray and , we can calculate the answer for the subarray in time.
- Disjoint subarrays can be "combined" independently.
- (the size of ) is usually not greater than .
This technique relies on the assumption that we can "combine" two subarrays and to get a candidate for . We can thus iterate over all and find the best possible answer for . (Note that we need to process subarrays in increasing order of length!)
Since there are subarrays and processing each one takes time, solutions using this technique generally run in time.
Focus Problem – try your best to solve this problem before continuing!
Solution - Space Jazz
Time Complexity:
While it may be tempting to use a greedy approach (e.g. repeatedly erasing
matching letters until you can't anymore, and then erasing the first "bad"
letter), this approach doesn't work on inputs like ababa
. Combined with the
fact that here, this suggests that we should use dynamic
programming on ranges.
Let's consider the above test case - which a
(if any) should we match the
first letter with? Since is small, we may as well try each other a
, but
then how do we deal with the resulting "gaps" in the string?
The key observation is that if we match it with the second a
in the string,
then we can't match the two b
s together. This means that we don't actually
need to care about the gaps from matching letters! More specifically, if it's
optimal to match with , then the minimum number of insertions for
is the sum of the minimum number of insertions for and
.
We can thus use dynamic programming on ranges to find, for each substring of , the minimum number of insertions needed to turn it into space jazz.
(Don't forget to consider the case where we don't match with anything, and just duplicate it!)
C++
#include <bits/stdc++.h>using namespace std;int dp[502][502]; // Min additions to get "jazz" from index i to j// Inclusive and 0-indexedint main() {cin.tie(0)->sync_with_stdio(0);string s;cin >> s;
Java
import java.io.*;import java.util.*;public class Jazz {public static final int MAXN = 500;public static void main(String[] args) throws IOException {Kattio io = new Kattio();char[] inp = io.next().toCharArray();// DP[i][j] is the min number of additions to get "jazz" from index i to
Python
s = input()n = len(s)dp = [[0] * (n + 1) for _ in range(n + 1)]for i in range(n + 1):for j in range(n - i):dp[j][i + j] = dp[j + 1][i + j] + 1for k in range(j + 1, i + j + 1):if s[k] == s[j]:dp[j][i + j] = min(dp[j][i + j], dp[j + 1][k - 1] + dp[k + 1][i + j])print(dp[0][n - 1])
Problems
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
Old Gold | Easy | Show TagsRange DP | |||
Gold | Easy | Show TagsRange DP | |||
Gold | Easy | Show TagsRange DP | |||
CF | Easy | Show TagsRange DP | |||
Gold | Normal | Show TagsRange DP | |||
CSES | Normal | Show TagsRange DP | |||
CF | Normal | Show TagsRange DP | |||
SAPO | Normal | Show TagsRange DP | |||
CC | Normal | Show TagsRange DP | |||
Baltic OI | Hard | Show TagsRange DP | |||
Platinum | Hard | Show TagsRange DP | |||
Platinum | Hard | Show TagsRange DP | |||
Platinum | Very Hard | Show TagsRange DP | |||
CEOI | Very Hard | Show TagsRange DP | |||
CF Gym | Very Hard | Show TagsRange DP |
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!