深度优先搜索 DFS

文章介绍了深度优先搜索(DFS)的基本原理,通过两个实例——全排列问题和迷宫问题,展示了DFS如何解决枚举路径和寻找解决方案的问题。在全排列问题中,DFS用于生成所有可能的数列;在迷宫问题中,DFS则用于探索所有可能的步法以找到终点。
摘要由CSDN通过智能技术生成
深度优先搜索就是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底…,不断递归重复此过程,直到所有的顶点都遍历完成。

下图为一棵树的深度优先遍历(蓝色数字表示遍历顺序):

DFS常用于解决有多少种情况、多少条路径、最大路径等。

核心算法:
void dfs(int dee){//dee是深度
    if(dee>n){//递归边界
        print();return;//如果达到n,那么输出
    }
    for(int i=1;i<=n;i++){//for轮流固定数字
        if(!gd[i]){//判断数字是否用过
            gd[i]=1;//若没用过,将其标记为用过
            a[dee]=i;//将这个数字固定下来
            dfs(dee+1);//递归深搜
            gd[i]=0;//深搜完毕,将其取出,开始下一轮
        }
    }
    return;
}

例题1:洛谷P1706 全排列问题

题目描述:

这是一道很标准的深搜题,求n个数的排列情况有多少种并把它们全输出。

解题代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;//输入的数
int a[15],b[15];//第一个用来标记数有没有选过,第二个标记输出数的顺序
void sc(){//输出函数
    for(int i=1;i<=n;i++)
        printf("%5d",b[i]);//注意题目要求“每个数字保留5个常宽”
    cout<<endl;//换行
}
void dfs(int l){
    if(l>n){//判断停止条件
        sc();//调用函数
        return;//返回
    }
    for(int i=1;i<=n;i++){//循环
        if(!a[i]){//如果数没有被选过
            a[i]=l;//数被选过了
            b[l]=i;//数是第几个被选的,也就是输出顺序
            dfs(l+1);//回溯
            b[l]=0;
            a[i]=0;
        }
    }
}
int main(){
    cin>>n;//输入
    dfs(1);//调用函数
    return 0;
}

例题2:洛谷 P 1065 迷宫

题目描述:

迷宫问题也是很典型的深搜题目,因为要枚举走的步数,以及走错路时退回来换下一条路。

解题代码如下:

#include<bits/stdc++.h>
using namespace std;

bool G[15][15],VIS[15][15];//G为总地图,VIS记录是否访问
int n,m,d[5]={-1,0,1,0,-1};//方向不解释 
int nx,ny,ex,ey,CNT;
//nx,ny起点坐标;ex,ey终点坐标,CNT路径条数

void dfs(int x,int y)
{
    if (x ==ex&&y ==ey)//如果到终点
    {
        CNT++;//路径加一
        return;//回去继续查找
    } 
    for (int k=0;k<4;k++)
    {
        int l=x+d[k];int r=y+d[k+1];
        if (l>=1&&r>=1&&l<=n&&r<=m&&!G [l][r]&&!VIS [l][r]) 
        {
            VIS [l][r]=true;//标记为已访问
            dfs (l,r);
            VIS [l][r]=false;//回溯
        }
    }
    return; 
}
int main ()
{
    int t,zx,zy;
    cin>>n>>m>>t>>nx>>ny>>ex>>ey;
    G[nx][ny]=true; //这就是许多人(我)40分的原因
    //因为dfs函数里并没有将起点设为已访问
    //所以在后面的访问里,可能访问起点许多次
    //所以你的答案可能比标准答案多
    while(t--)
    {
        cin>>zx>>zy;
        G[zx][zy]=true;//设为障碍
    } 
    dfs (nx,ny);//从起点开始寻找 
    cout<<CNT;
    return 0; 
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值