深度优先搜索(DFS)是非常重要的一个内容,深度优先搜索有三个重要的点:
- 出口(终止条件):决定何时结束当前分支
- 状态标记与回溯:保证不重复访问并能回溯上一个状态
- 遍历顺序与剪枝:决定搜索效率并提前排除无效分支
而每个程序由于所求的东西不同,出口、状态标记与回溯、遍历顺序与剪枝也都不相同,有些程序不需要回溯,也有些程序不需要状态标记。
下面是基础 DFS 的伪代码框架:
voiddfs(intd){if(出口){操作;return;}for(循环次数){if(合法的条件){状态标记;dfs(d+1);回溯;}}}而 DFS 用的比较多的地方就是跑迷宫,下面是一道关于迷宫的例题:
P1605 迷宫
我们可以从起点开始,往上、下、左、右四个方向走,只要下一个位置不是障碍物,就可以走,把走过的位置都进行标记,标记过的地方不能往回走,只要当前位置为终点位置,就把答案加一。
下面是本题的代码:
#includeusingnamespacestd;constintmaxn=15;intn,m,t,sx,sy,fx,fy,ans,vis[maxn][maxn];intdx[]={-1,0,1,0};intdy[]={0,1,0,-1};charmp[maxn][maxn];voiddfs(intx,inty){if(x==fx&&y==fy){ans++;return;}for(inti=0;i<4;i++){intxx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&mp[xx][yy]!='#'){vis[xx][yy]=1;dfs(xx,yy);vis[xx][yy]=0;}}}intmain(){cin>>n>>m>>t>>sx>>sy>>fx>>fy;for(inti=1;i<=n;i++){for(intj=1;j<=m;j++)mp[i][j]='.';}for(inti=1;i<=t;i++){intx,y;cin>>x>>y;mp[x][y]='#';}vis[sx][sy]=1;dfs(sx,sy);cout<<ans;return0;}其中,dx和dy表示四个方向,mp是迷宫的地图。
对于其他的 DFS 题目,只要找到了出口、状态标记与回溯、遍历顺序与剪枝,就可以很轻松的把题目写出来。