DFS基于递归思想,有两个重要的标志,也就是两个数组,一个用来标记该点是否被访问过,一个用来把该点放入数组---即存答案.
//注意bool数组初始化默认为false
模板
void dfs()//参数用来表示状态,一般什么在变化什么作参数.
{
if(到达终点状态)
{
...
return;
}
if(越界或者是不符合法状态)//剪枝
return;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
....//根据题意来添加
标记;
dfs();
修改(剪枝);
(还原标记);//此处直接按正常思维,这一位存完了,恢复
//是否还原标记根据题意,如果加上(还原标记)就是 回溯法
}
}
}
几个注意点
1.不要把递归想得太复杂,即有时候不用一定要把递归想到底,就按正常思维,处理掉当前的工作,下一步交给下一步递归去完成,每一步递归都完成自己工作就皆大欢喜.
2.扣几个细节
2.1.以三的全排列为例,完成第一次123排列,回到2的位置时,存放数字2的赋值步骤已经结束,下一步执行的是恢复现场即把2恢复,然后for循环就会跳到存放数字3的步骤,把3存入第二个位置,dfs靠的就是这样不会重复把2再存放进去(其实和第一点说的一样,不用扣的太深,自己会解决问题).
2.2.for循环只是遍历数字,实际上如果不进入if的话,一直是在当前位置--要存放的第几个位置,只有进入之后才会进入下一个位置,注意不能搞混位置和数字
3.要注意下标,留意数组思维惯性,应该从1开始,从0会错位
4.自己可以调试一步一步走一遍,印象会深很多.
acwing样例
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j]) dfs(j);
}
}