问题:输入n,m表示迷宫的规模n行m列,之后n行输入迷宫的值, '.'表示路,'*'表示墙,'s'表示起点,'T'表示终点,找出迷宫的解并用字符m标记路线。
#include<iostream> using namespace std; int n,m; //规模 char maze[105][105]; //存储迷宫的值 bool vis[105][105]; //用来存储这个点是否走过 int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; //四个方向分别是 上左下右 逆时针 bool in(int x,int y){ if(x>=0&&x<n&&y>=0&&y<m){ return true; } return false; } //in函数用来判断是否越界 bool dfs(int x,int y){ if(maze[x][y]=='T'){ return true; }//找到直接返回true if(in(x,y)&&!vis[x][y]&&maze[x][y]!='*'){ vis[x][y]=true; maze[x][y]='m';//满足条件的点,标记走过,做上标记m for(int i=0;i<4;i++){ if(dfs(x+dir[i][0],y+dir[i][1])){ return true; } }//往四个方向搜,一种穷尽的枚举法 vis[x][y]=false;//如果找到了会提前return true;走到这一步则表示该点搜下去找不到,那么该点取消标记,把标记m去掉 maze[x][y]='.'; return false;//返回false } } int main(){ int x,y; //用来标记起始点的坐标 cin>>n>>m; for(int i=0;i<n;i++){ cin>>maze[i];//将整个迷宫的值输入 } for(int i=0;i<=n;i++){ for(int j=0;j<=m;j++){ if(maze[i][j]=='S'){ x=i; y=j;//找到迷宫起始点的坐标 } } } dfs(x,y);//找迷宫的解 for(int i=0;i<n;i++){ cout<<maze[i]<<endl;//输入带标记解的迷宫 } return 0; }
这里的dfs采用的是一种递归的思想,4个方向相当于4次递归,4个方向上递归,图中表示起点先一直往上走到黑,走到黑后,再往左走到黑,图中采用的是逆时针的顺序,当从第一个点往上走到第二个点,第二个点的dfs同第一个一样也是先判断是否找到终点,若没有则采取和第一个点一样的策略,先往上走到黑,再往左走到黑,一种逆时针的方向,以此递推,至到最后一个点,最后一个点的4次dfs都是return false,因为4个方向都无路可走,所以最后一个的代码执行到将该点的vis取消标记,同时取消该点的m标记,因为最后一个点没有返回true所以倒数第二个点也没有返回true,倒数第二个点中的dfs代码以此往下执行到,vis取消标记,同时取消m标记,以此回溯到第一个点,此时第一个点的第一个方向的dfs并不能走通,进入第二个方向的dfs,其中过程同上述的类似,直到找到终点,return true,反之 return false。