递归,递推,记忆化搜索总结
将这三种相似的算法(?)一起做出比较
以便于更好的复习(? )
一.递归、记忆化;
一个函数在他的函数体内调用它自身称为递归调用,这种函数称为递归函数。执行递归函数将反复调用自身(也就是相当于嵌套函数),每一次的调用就进入新的一层函数,执行到最后结束的那一行代码就开始从里面一层一层的退出函数
而这里有一些技巧
- 边界值,判断退出递归条件
- 递归特性,递归输出的前后逻辑
- 通过记忆化空间换时间
- 不同情况下 void 与 int 的灵巧转换
- 回溯思想
1.边界值
一个递归如果没有边值就成了死循环,根据题目特判
2.输出前后逻辑
例如在 一个dfs 函数前后加上输出“…”
就可以确认输出顺序
e.g:
dfs(x,y+1);
//递归特性
if ( x!=0 && t!=0 ) cout<<"+";
3.记忆化搜索 空间换时间
记忆化,顾名思义,让电脑程序记住自身递归下的数,使得出现过的不必要再计算一次,从而大大节省时间
就例如递归函数这道题
虽然很简单,题目已将公式给出
但如果不使用记忆化,就会少拿30分
有时候我们也可以使用 多维数组判断是否搜索过
就例如上述那道题,我选择使用三维数组,并且使用 memset 函数直接全附上-1;
而当这个函数操作个特定数,自然就不为-1;便可实现记忆化
4.void int巧转换
这里是我个人觉得的一个易错点
当为空函数时,可以直接在主函数中调用
但通常情况下不会调用超过1次
而当我们记忆化时,一般情况下用的是int
输出时,即cout<<dfs(h,y,x.....); 即可
5.回溯
类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径
当前局面下,我们有若干种选择,所以我们对每一种选择进行尝试。如果发现某种选择违反了某些限定条件,此时
return;如果尝试某种选择到了最后,发现该选择是正确解,那么就将其加入到解集中。
利用巧妙的反求方法,更好的寻得每一层递归的情况
二.递推
相较于递归,个人理解递推较好理解
即寻找有一定关系的两数的关系式,利用固定的(自己求出,或题目中给出)的关系式进行赋值和求解
偏于数学思维
有顺序和逆序两种递推方法
即从后往前和从前至后推得方法
往往花费大量时间寻找规律,而代码实现只需要几分钟
个人认为要善于运用电脑所带的画图工具或excel表进行模拟,对样例进行分析~