dp给我的感觉就相当于dfs。只不过dp是从一个集合推到另一个集合。在思考dp的时候可以思考一下如果dfs的话,它是如何推出答案的。也就是说,我们不用关心具体的dfs过程,但要知道它是如何从无到有,算法推进过程中得到中间结果的顺序是什么。把这些中间结果放到一个集合中,就是dp。
最长上升子序列模型
数字三角形模型
有些题目,要求你求出一个最佳序列。这个序列的元素不一定是数。
先要知道一个定理:B序列的所有元素肯定都在A序列中出现过。
在得到答案的算法推进过程中,我们要暴力枚举出所有的B序列。在暴力枚举所有B序列的过程中,也会枚举出一些中间序列(类似于dfs中的状态节
点)。将这些序列按某一特征进行划分。
集合:{i, j}:与A[1……i]配对,且以A1[j]结尾的B序列。(A1[j]是排序好的A序列)
属性:dp[i][j] : MIN S
集合划分:遮掉A[j],所有的序列都可以唯一映射到{i - 1, k}中{1 <= k <= j}。
所以dp[i][j] = min(dp[i - 1][k] + abs(A[i] - A1[j]);
题目让求最小花费,实际上就是让你去求出一个最佳序列,这个序列的每个元素是服务员移动。按照这个序列,能够得到最小花费。
要求最小化的花费,就要知道具体的安排方案;因此问题等价于求最小花费的安排方案。得到安排方案是一个从无到有的过程,我们把过程中的一些
中间方案放到一个集合中,用集合来推动算法的过程,就能大大降低时间复杂度。
f[i][x][y]
集合:完成了前i个请求且三个服务员在p[i], x, y的所有安排方案集合。
属性:MIN花费
状态划分太复杂,我们可以看看{i, x, y}可以到哪些集合:
{i, x, y} —>
1.如果派x到p[i + 1]:{i + 1, p[i], y}
2.如果派y到p[i + 1]:{i + 1, x, p[i]}
3.如果派p[i]到p[i + 1]:{i + 1, x, y}