这节课讲解dfs,通过两个例子,全排列和八皇后
递归相对于人的大脑思考方式,比较抽象。
递归是不是把问题不断规约成子问题? 是不是很像数学归纳法?
那我们该如何学习递归问题呢? 是不是递归问题不够直观?那我们是不是可以画一个递归搜索树,让我们更容易理解过程呢。
全排列问题
画出全排列的递归搜索树,各种节点很多。那我们该怎么样处理呢?仔细观察可以发现,节点看起来很多,但是可以抽取很多共同点。
那么如何抽取(规约)呢?何如归约到一个函数里呢?
char path[]; // 使用path记录方案。
void dfs(int u) // 是不是需要知道当前在哪一层呢?那么使用u记录当前搜索到哪一层
{
if(u==n) {} // 如果到了最后一层,直接输出,输出方案。输出是不是需要用数组记录呢?
else
{
// 没走到最后一层,是不是说明现在需要枚举当前要填什么?
for(int i=0;i<n;i++)
if(!st[i]) // 是不是需要保证和前面的没有重复呢?
{
path[u] = s[i]; // 填上第i个字母
st[i] = true; // 标记第i个字母
dfs(u+1); // 是不是可以进入下一层了?
st[i] = false; // 回溯的时候,记得恢复现场
}
}
}
八皇后问题
问题描述:一个8*8大小的国际象棋棋盘,放有八个皇后,让八个皇后处于彼此不能相互攻击的范围,求一共有多少种摆放方式?
解决方法:暴力搜索。 那么该如何暴力搜索呢? 如果很直接的枚举每一个格子,放或者不放两种状态,你会发现计算量太大。
这个时候,该考虑如何优化呢? 考虑宏观的特性,每个皇后是不是不能放在同一行,那么是不是说明每一行都要有而且只有一个皇后。
这样思考,会发现问题的复杂度会大大降低。
那么,现在的思路就是枚举第一行皇后的方法,然后深搜。简化来看,特别像全排列--即枚举八列,每一列不能重复。现在是不是问题解决了大半呢。
现在唯一需要考虑的是,如何满足皇后也都不再同一对角线上。
这里正对角线 2n-1条, 反对角线2n-1条. 想办法找到格子和对角线之间的转化关系。
上面的图片,是不是一种映射方式(b=x+y与 b=x-y)?是不是同一条对角线上的点,都可以用这个函数表达?
所以这样来看,这道题相对来说很容易解决了。
标签:辅导课,递归,是不是,dfs,枚举,对角线,皇后,考研
From: https://www.cnblogs.com/spock12138/p/17132083.html