深度优先搜索DFS

深度优先搜索的关键在于递归,在递归的同时还要对路径不断加以标记。
基本流程如下:

  1. 定义dfs函数,函数的参数就是搜索过程中不断迭代的变量;
  2. 定义标志数组,路径每经过一个点,就要将该点标记,一条路径不能重复经过同一个点,防止路径出现回环;
  3. 每到达一个新的点,先将其标记。若符合最终条件,则将成功标志位置1,并立即return;若不符合,且不能进一步深入,则直接return;若不符合但是可以进一步深入,则递归深入探索,返回时记得将标记取消。

注意:深度优先搜索不会同一个点上,重复选择上一个已经被抛弃的方向,而是不断选择新方向探索,新路线都是有限的,因此深度优先搜索有穷尽的时刻!

核心代码如下:

    mark[x][y] = true;  //给该位置标记,避免重复经过该点
    if(maze[x][y] == 'D' && t<=time){  //到达且没有超时
        success = true;
        return;
    }else if(maze[x][y] == 'X'|| t>time){ //遇到墙或者超时
        return;
    }else if(t<=time-1){  //未到达,且下一步不会超时
        if(x+1<=n-1 && mark[x+1][y]!=true){  //没有越界且未被标记
            dfs(x+1,y,t+1);
            if(success == true) return;
            mark[x+1][y] = 0;

        }
        if(x-1>=0 && mark[x-1][y]!=true){
            dfs(x-1,y,t+1);
            if(success == true) return;
            mark[x-1][y] = 0;

        }
        if(y+1<=m-1 && mark[x][y+1]!=true){
            dfs(x,y+1,t+1);
            if(success == true) return;
            mark[x][y+1] = 0;

        }
        if(y-1>=0 && mark[x][y-1]!=true){
            dfs(x,y-1,t+1);
            if(success == true) return;
            mark[x][y-1] = 0;

        }
    }

这里给出一个例题:
在这里插入图片描述
代码:

#include <iostream>
#include <stdio.h>
using namespace std;

char maze[8][8];  //记录地图
int mark[8][8];  //dfs遍历时用于标记
int n,m,time;  //长宽和时间
int srow,scol,drow,dcol;  //起点和终点
int success;  //记录是否成功

//深度优先搜索,深度优先搜索不会回头重新选择那条已经被抛弃的路线,
//因为已经在上一个if语句选择过了,所以dfs的递归会有穷尽
void dfs(int x,int y,int t)
{
    mark[x][y] = true;  //给该位置标记,避免重复经过该点
    if(maze[x][y] == 'D' && t<=time){  //到达且没有超时
        success = true;
        return;
    }else if(maze[x][y] == 'X'|| t>time){ //遇到墙或者超时
        return;
    }else if(t<=time-1){  //未到达,且下一步不会超时
        if(x+1<=n-1 && mark[x+1][y]!=true){  //没有越界且未被标记
            dfs(x+1,y,t+1);
            if(success == true) return;
            mark[x+1][y] = 0;

        }
        if(x-1>=0 && mark[x-1][y]!=true){
            dfs(x-1,y,t+1);
            if(success == true) return;
            mark[x-1][y] = 0;

        }
        if(y+1<=m-1 && mark[x][y+1]!=true){
            dfs(x,y+1,t+1);
            if(success == true) return;
            mark[x][y+1] = 0;

        }
        if(y-1>=0 && mark[x][y-1]!=true){
            dfs(x,y-1,t+1);
            if(success == true) return;
            mark[x][y-1] = 0;

        }
    }
}

int main()
{
    while(cin>>n>>m>>time && n!=0 && m!=0 && time!=0){
        success = 0;  //标志位归零
        for(int i=0;i<8;i++){  //地图与遍历标志数组归零
            for(int j=0;j<8;j++){
                maze[i][j] = 0;
                mark[i][j] = 0;
            }
        }

        for(int i=0;i<n;i++){
            cin>>maze[i];
            //获取起点坐标
            for(int j=0;j<m;j++){
                if(maze[i][j] == 'S'){
                    srow=i;scol=j;
                }
            }
        }

        dfs(srow,scol,0);
        if(success == true){
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    }
}

/*
输入:
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D

输出:
NO
YES
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值