Inspired by nor's blog (with permission). See comparison at the end of the post. And check his blog out. There's some interesting stuff on it :D
Disclaimer: You need C++17 for this to compile.
Introduction
When writing recursive DP, one usually need to save the result of a call (memoization) to prevent excessive computation. In python it's as easy as using a decorator:
from functools import cache
@cache
def fibo(n):
return n if n <= 1 else fibo(n - 1) + fibo(n - 2)
In C++ you'd typically declare a multi-dimensional array, populate it with an unused constant, check if [x][y][z] has been calculated and finally store the result for later use. So much boilerplate... What if you could just paste a code snippet (from code editor or a file) and start solving the problem instead?
DP cache
Let's skip over the implementation details and talk about the interface and how to use it. All you should care about is:
use_cache<R, N>(array<int, N> ds, F f);
Where:
Ris the type of the DP state.Nis how many dimensions you need to use.dsspecifies the size of each dimension in the internal N-D array.fis a lambda with a function signature similar to(auto &self, int, char, bool, ...) -> R.
Example usage
Here's the code to count how many integers in the range $$$[1; n]$$$ have the sum of their digits divisible by $$$k$$$:
Notes
Difference from nor's implementation
Uses a std::vector internally rather than a __gnu_pbds::gp_hash_table so:
- Around 2-4 times faster.
- Less flexible, only works with integers in parameters, whereas with a hash table you can have arrays, vectors, tuples, etc.
Shh I know it's common to find a problem needing top down DP. It is just that this is something interesting to try and implement.







