Note and codes while studying the book Advanced Design And Analysis Techniques, 4th edition. Mainly chapter 14, on dynamic programming and greedy algorithms (Ada LeetCode hard).
Table of Contents
- Advanced Design And Analysis Techniques
Steps to develop a dynamic programming algorithms:
- Characterise the structure of an optimal solution.
- Recursively define the value of an optimal solution.
- Compute the value for an optimal solution, usually bottom-up approach.
- Construct an optimal solution from computed information.
Including Top down (recursion using call stack) and bottom up (iterative, using array or min variables) method as it is the simplest showcase of recursion for myself to refresh these content.
Optimal substructure problem: optimal solution are composed of optimal sub-solution, basically meaning it can be solved recursively.
The recursive structure for the problem can be decomposed of first piece to be the left-hand end, and right-hand end to be the maximum/optimal price of the total length.
If you implement the above method, you will find the function get considerably slower exponentially. This problem exist with top down recursive approach, because we are recalculating each sub-problem again every time for each level it goes up.
As a tree with each node equals to a function call, for a rob length of
Dynamic programming approach to solve the problem of recalculating sub-problem, is to instead save the solution of the sub-problem and reuse as needed!
This is a classic case of time-memory trade-off (like hashing). Where time is saved using more memory (for saving sub-problem results.)
The implementation here uses a an extra array size of maximum length of rod, which passes around by reference.
Same approach but different execution to above Fibonacci bottom up method. Solve and save sub-problem results in ascending
order (smallest first), and reuse results.
Given a sequence
The amount of computation of this problem is dominated by the number of scalar multiplications, where
For
If we use another configuration
As an example, substituting
The actual dynamic problem to solve is to find the optimal parentheses order that gives the minimum scalar multiplications.
The optimal parenthesization for
Let
- BFS
- DFS
- Topological sort
- Weighted graph (Dijkstra's Algorithms)
cmake -S . --preset=debug -B build
or
cmake -S . --preset=release -B build
then run
cmake --build build
or
cd build && ninja clean && ninja
and executable will exist in the build/
directory.
to generate compile_commands.json file for clangd LSP, use
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .. --preset=${PRESET_NAME}
cd ${ROOT_DIRECTORY}
ln -s build/compile_commands.json