# 算法技巧总结
# 动态规划
动态规划,无非就是利用历史记录,来避免我们的重复计算。而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者二维数组来保存。
# 第一步骤
定义数组元素的含义,上面说了,我们会用一个数组,来保存历史数组,假设用一维数组 dp[] 吧。这个时候有一个非常非常重要的点,就是规定你这个数组元素的含义,例如你的 dp[i] 是代表什么意思?
# 第二步骤
找出数组元素之间的关系式,我觉得动态规划,还是有一点类似于我们高中学习时的归纳法的,当我们要计算 dp[n] 时,是可以利用 dp[n-1],dp[n-2].....dp[1],来推出 dp[n] 的,也就是可以利用历史数据来推出新的元素值,所以我们要找出数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],这个就是他们的关系式了。而这一步,也是最难的一步。
# 第三步骤
找出初始值。学过数学归纳法的都知道,虽然我们知道了数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],我们可以通过 dp[n-1] 和 dp[n-2] 来计算 dp[n],但是,我们得知道初始值啊,例如一直推下去的话,会由 dp[3] = dp[2] + dp[1]。而 dp[2] 和 dp[1] 是不能再分解的了,所以我们必须要能够直接获得 dp[2] 和 dp[1] 的值,而这,就是所谓的初始值。
由了初始值,并且有了数组元素之间的关系式,那么我们就可以得到 dp[n] 的值了,而 dp[n] 的含义是由你来定义的,你想求什么,就定义它是什么,这样,这道题也就解出来了。
# 回溯
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。
用回溯算法解决问题的一般步骤:
- 针对所给问题,定义问题的解空间,它至少包含问题的一个(最优)解。
- 确定易于搜索的解空间结构,使得能用
回溯法方便地搜索整个解空间 。- 以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。
回溯法可以理解成为通过选择不同的岔路口,来寻找目的地,一个岔路口一个岔路口的去尝试找到目的地,如果走错了路的话,继续返回到上一个岔路口的另外一条路,直到找到目的地。
# 基本套路
- 「路径」:记录做出的选择。
- 「选择列表」:通常而言,用数组存储可以选择的操作。
- 「结束条件」:一般而言,就是递归的结束点,也就是搜索的结束点。
- 「回溯优化」 :配合剪枝函数进行优化,通过这个函数,我们可以减去一些不可能到达到终点的条件,