DFS中的迷宫问题

问题:输入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。

猜你喜欢

转载自www.cnblogs.com/jcahsy/p/12451759.html