dfs是最广泛的搜索算法,通俗讲就是:一条路走到黑,通过暴力枚举,将所有可能的情况一一枚举,不断地试探来找到解
对每一个可能的分支路径深入到不能再深入,而且每个顶点只访问一次。
dfs一般借助递归来实现:
1 void dfs(int deep){ 2 if(到达边界){ 3 //做一些处理后返回 :回溯 4 } 5 else{ 6 for(所有的可能){ 7 dfs(deep+1); 8 } 9 } 10 }
以走迷宫为例:
我们尝试用dfs来解决这一问题,伪代码:
1 int vis[1000][1000]; 2 int xx[4]={1,0,-1,0}; 3 int yy[4]={0,1,0,-1}; 4 void dfs(int x,int y){ 5 if((x,y)到达终点){ 6 方案数ans++; 7 return ; 8 } 9 标记(x,y)已经访问过 10 else{ 11 /*for(x,y能到达的格子tx,ty){ 12 if(tx,ty没有被访问过且合法){ 13 dfs(tx,ty); 14 }*/ 15 for(int i=0;i<4;i++){ 16 int tx=x+xx[i]; 17 int ty=y+yy[i]; 18 if(!vis[tx][ty]&&tx和ty在地图之内没有出界){ 19 dfs(tx,ty); 20 } 21 } 22 取消(x,y)访问标记//这是重点,必须要取消 23 }
最终代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 int cnt=0;//最终结果 5 int vis[20][20];//记录每个点的访问情况 6 int sx,sy;//起点坐标 7 int ex,ey;//终点坐标 8 int xx[4]={0,0,-1,1};//xy方向的两个方向数组,分别往上下左右方向走 9 int yy[4]={1,-1,0,0}; 10 int mp[20][20];//记录地图 11 //搜索 12 int dfs(int x,int y){ 13 if((x>=0&&y>=0)&&(x<n&&y<m)&&(mp[x][y]==0)){//坐标点在地图之内且可行 14 if(x==ex&&y==ey){//如果是终点,cnt++ 15 cnt++; 16 return 0; 17 } 18 } 19 vis[x][y]=1;//设置已访问 20 if(vis[x][y]==1){//对于这个点,继续往下搜索 21 for(int i=0;i<4;i++){ 22 int tx=x+xx[i]; 23 int ty=y+yy[i]; 24 if((vis[tx][ty]==0)&&(tx>=0&&ty>=0)&&(tx<n&&ty<m)&&(mp[tx][ty]==0)){//未被访问过且点在图之内且mp可行 25 dfs(tx,ty); 26 } 27 } 28 } 29 vis[x][y]=0;//取消标记 30 } 31 int main(){ 32 memset(vis,0,sizeof(vis)); 33 cin>>n>>m; 34 for(int i=0;i<n;i++){ 35 for(int j=0;j<m;j++){ 36 char c; 37 cin>>c; 38 if(c=='.'){ 39 mp[i][j]=0; 40 }else if(c=='S'){ 41 sx=i; 42 sy=j; 43 mp[i][j]==0; 44 }else if(c=='T'){ 45 ex=i; 46 ey=j; 47 mp[i][j]=0; 48 }else{ 49 mp[i][j]=1; 50 } 51 } 52 } 53 dfs(sx,sy); 54 cout<<cnt<<endl; 55 return 0; 56 }