[算法浅析] dfs(爆搜大法好)

没有什么是暴搜搜不出的,如果有,请多给他点时间

DFS(Depth-first search)中文名为深度优先搜索,顾名思义,其核心思想为沿着一条路走下去,直到无法往下走就返回。

相比bfs,dfs的特点就是暴力,这暴力的思想也可以让dfs做一些其他题,如方案数,模拟。
时间复杂度也是高


举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束).

[算法浅析] dfs(爆搜大法好)_第1张图片


dfs函数自己调用自己时,会生成一个“新的”函数,在函数里定义的变量会重新覆盖,但不会把之前的函数里的变量覆盖。
如果你定义的全局变量,那还是会永久变更。
当函数执行完后return 会回到上个调用它的函数的语句位置。


dfs一般用函数调用本身,栈,来实现

dfs模板

void dfs(状态){
	if(无法再更新状态){
		得出答案
	}
	if(剪枝条件满足 当前状态无用){
		return;
	}
	for 扩展状态
		(标记)//防止多次更新已算出的状态
		dfs(更新状态);
		(清除标记)
}

这多次调用本身,使dfs时间复杂度一般n^2起步

例题

马的遍历
Description

中国象棋大家都玩过吧!!!-
现在有只小马迷路了,它现在在0,0位置,它的家在m,n位置(棋盘大小为m*n),现规定小马只能往右走,请聪明的你帮帮小马算一下回到家有几种方案?

Input

家的位置m,n 比如4,8 1=

Output

一个整数即方案数

Sample Input

4 8

Sample Output

37

#include
using namespace std;
int n,m;
bool vis[1010][1010];
int dir[4][2]={{1,2},{2,1},{-1,2},{-2,1}};
bool in(int x,int y){
    return x>=0 && y>=0 && x<=n && y<=m;//判断出界
}
int cnt;
void dfs(int x,int y){
    if(x==n && y==m){//到达终点
        cnt++;
    }
    for(int i=0;i<4;i++){//扩展4个方向
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        if(in(tx,ty) && !vis[tx][ty]){
            vis[tx][ty]=1;//防止多次走同个路径
            dfs(tx,ty);
            vis[tx][ty]=0;
        }
    }
}
int main(){
    cin>>n>>m;
    dfs(0,0);
    cout<<cnt;
    while(1);
    return 0;
}

常见问题

  • dfs陷入死循环会直接RE,比起bfs让你电脑冒烟更安全,那多半是你出口条件,标记写得有问题。
  • dfs时间复杂度极高,当你看到n极大时考虑剪枝或换个算法吧。
  • 在dfs里开的变量不会用到全局,但会在return时返回。

你可能感兴趣的:([算法浅析] dfs(爆搜大法好))