码迷,mamicode.com
首页 > 其他好文 > 详细

深度优先搜索---一个懵逼的东东

时间:2019-08-22 11:00:43      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:序列   全排列   for   结果   输出   bit   printf   打印   arch   

深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次.(来自百度百科)

先解释以下深度:

深度指在搜索的过程中沿着一条路一直向下进行,直到这条路没有下一个节点停止,然后返回到上一步接着进行上述操作

所以深度优先搜索的整体结构就是:

1.递归2.剪枝

可能这样说有点不清楚,举个例子

打印1-4的全排列开头为1和2的所有序列;

1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1

上述是由编译器进行深搜算法打印的1-4的全排列开头为1和2的所有序列

下面是运行的代码

#include<bits/stdc++.h>
using namespace std;
int n,pd[100],used[100];//pd是判断是否用过这个数
void print()//输出函数
{
    int i;
    for(i=1;i<=n;i++)
    printf("%5d",used[i]);//保留五位常宽
    cout<<endl;
}
void dfs(int k)//深搜函数,当前是第k格
{
    int i;
    if(k==n) //填满了的时候
    {
        print();//输出当前解
        return;
    }
    for(i=1;i<=n;i++)//1-n循环填数
    {
        if(!pd[i])//如果当前数没有用过
        {
            pd[i]=1;//标记一下
            used[k+1]=i;//把这个数填入数组
            dfs(k+1);//填下一个
            pd[i]=0;//回溯
        }
    }
}
int main()
{
    cin>>n;
    dfs(0);//注意,这里是从第0格开始的!
    return 0;
}

我们通过上述举例以及举例所用代码来进行分析:

比如我们发现输出的第一行是1 2 3 4,第二行是1 2 4 3

为什么一行会输出四个数字?是因为剪枝,即在递归函数中下一个判定条件,也就是深搜搜索到这一步已经没有路能走了

上边解释剪枝可能有点笼统,简单的说就是走到这,不能往下走了

为什么要有剪枝呢?很显然根据剪枝的定义,就是避免遍历的时候越界,或者去掉影响结果的因素

第二个问题,为什么第一行是1 2 3 4,而第二行是1 2 4 3?

因为在其中进行递归操作,在这先说一个标记数组,这个数组作用是,对所已经便利过的数进行标记,下来我们看下标记数组的记录过程

我们开始运行程序输入4:

进入dfs(0),dfs()中系数表示已经确定几个数的输出,下来遍历1-4发现pd[1]=0,标记1,即pd[1]=1,used[1]=1

下来进行dfs(1)遍历1-4发现used[1]=1,跳过,下一个pd[2]=0,标记2,即pd[2]=1,used[2]=2

依次一直到dfs(4)遍历时发现,满足剪枝条件,输出第一行1 2 3 4

下来进行递归的回溯操作,即在dfs(3)的时候我们标记pd[4]=1;现在回溯pd[4]=0,这样在dfs(3)中的for遍历结束

下来到了dfs(2)是for遍历到i=3的时候进行的上面的dfs(3)的递归结束,所以回溯pd[3]=0,此时dfs(2)中的i=3结束,进行i=4遍历的pd[i]=0,所以used[2+1]=4,即pd[4]=1;

下来进行dfs(2)是i=4的dfs(3)递归,当i=3时pd[i]=0,所以used[3+1]=3,pd[3]=1,下来进行dfs(4)递归

此时达到剪枝边界,进行输出,得到1 2 4 3

然后下来进行..........

算了不写了,太累了,剩下递归,剪枝,回溯按照上面的步骤进行即可

简单的说就是

dfs(k)
{
        if(k==n)剪枝
for()遍历所有,和上面if没关系 { 如果未标记 { 标记 dfs(k+1)递归 回溯 } } }

如果遍历的是图,那么就是遍历相同深度未标记的子节点,具体题目中如何使用看下https://www.cnblogs.com/RE-TLE/category/1531861.html里面的题目以及题解

以上来自一个练习时间长达一年的蒟蒻Acmer,有事您Q我,我一直在de

 

深度优先搜索---一个懵逼的东东

标签:序列   全排列   for   结果   输出   bit   printf   打印   arch   

原文地址:https://www.cnblogs.com/RE-TLE/p/11392688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!