Memoization Search
Definition
Memoization search is a search implementation technique that avoids repeatedly traversing the same state by recording information about already visited states.
Because memoization search ensures each state is visited only once, it is also a common implementation method for dynamic programming.
Introduction
[NOIP2005] Herb Gathering
There are \(M\) different herbs in a cave. Picking each herb requires some time \(t_i\), and each herb has its own value \(v_i\). You are given a time period \(T\). Within this time, you can pick some herbs. Maximize the total value of the herbs collected.
\(1 \leq T \leq 10^3\), \(1 \leq t_i,v_i,M \leq 100\)
Naive DFS Approach
It is easy to implement a naive search approach: during the search, record three parameters—the current item to consider, the remaining time, and the accumulated value—then enumerate whether the current item is selected and transition to the corresponding state.
Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
The time complexity of this approach is exponential, so it cannot pass this problem.
Optimization
Why is the above approach inefficient? Because the same state is visited multiple times.
If we store the information of a state after computing it, we can directly use the previously computed information when we need to access that state again, thus avoiding repeated calculations. This fully utilizes the characteristic of many problems in dynamic programming having a large number of overlapping subproblems, embodying the "memoization" idea of trading space for time.
Specifically for this problem, we add an array mem to the naive DFS to record the return value of each dfs(pos, tleft). Initially, set every value in mem to -1 (indicating not yet computed). Each time we need to access a state, if the corresponding value in mem is -1, we recursively compute that state. Otherwise, we directly use the value already stored in mem.
With this processing, we ensure each state is visited only once, so the time complexity of this algorithm is \(O(TM)\).
Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
Connection and Differences with Iterative DP
When solving dynamic programming problems, memoization search and iterative DP code are highly similar in form. This is because they use the same state representation and similar state transitions. Also because of this, generally the time complexities of the two implementations are the same.
Below is the iterative DP implementation code (for ease of comparison, rolling array optimization is not added). By comparison, you can find their formal similarity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
When solving dynamic programming problems, both memoization search and iterative DP ensure that each state is solved at most once. However, the way they achieve this differs slightly: iterative DP avoids repeated access by setting an explicit access order, while memoization search, although not explicitly specifying an access order, achieves the same goal by marking already visited states.
Compared to iterative DP, memoization search does not require an explicit access order, sometimes making it easier to implement than iterative DP, and it can handle boundary conditions more conveniently. This is a major advantage of memoization search. However, at the same time, memoization search is difficult to optimize with techniques like rolling arrays, and due to recursion, its runtime efficiency is lower than iterative DP. Therefore, the more suitable implementation method should be chosen based on the problem.
How to Write Memoization Search
Method One
- Write down the DP state and equation for the problem.
- Write the dfs function based on them.
- Add the memoization array.
Example:
\(dp_{i} = \max\{dp_{j}+1\}\quad (1 \leq j < i \land a_{j}<a_{i})\) (Longest Increasing Subsequence)
Convert to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 | |
Method Two
- Write a brute-force search program for the problem (preferably dfs).
- Modify this dfs into a "no external variables" dfs.
- Add the memoization array.
Example: The "Herb Gathering" example in this article.
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用