算法专题之DFS

1.DFS是一种搜索算法,对每一个可能的分支路径深入到不能再深入为止,而且,每一个结点只能访问一次。
2.基本思路:从图中的某顶点a出发 - 访问顶点a - 依次从a的未被访问的邻接点出发,对图进行深度优先遍历,直至图中和a有路径相通的顶点都被访问 - 若此时图中尚有顶点未被访问,则从一个未访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。
3.举个例子吧!
输出1~n的全排列(全排列函数用法

例如1~3的全排列是123,132,213,231,312,321

大概思考一下我们会发现,每一位我们都是按照顺序进行排列的,第一位先放1,然后第二位放2,第三位放3,这样就完成了第一个排列,第二个排列我们将第二位的2换成了3,那么第三位就只剩下2,这样就完成了第二个排列,以此类推。

可以实际化一点,比如,把这个题目想象成往盒子里放球
那如何往盒子中放球呢?

for(int i = 0 ; i <= n ; ++i)
{
    a[step] = i;
}
//这一步表示将第i号球放到第step个盒子里

如果球被放过,就用一个标记数组来标记哪些球被放过。

for(int i = 1;i <= n; ++i)
{
    if(book[i] = 0)//book[i] = 0表示i号球没用被放过,还在手上
    {
        a[step] = i;//将i号球放到第step个盒子里
        book[i] = 1;//将book[i]变为1,表示第i个球已经被放过
    }
}

这样我们处理了第step个盒子,接下来需要处理下一个(即step + 1)个盒子,那么我们可以想到递归,即把刚刚的操作封装成一个函数,命名为dfs
代码如下:

void dis(int step)
{
    for(int i = 1; i <= n ; ++i)
    {
        //判断球是否被放过
        if(book[i] == 0)//说明i号球没有被放过
        {
            a[step] = i;将第i号球放到第step个盒子里
            book[i] = 1;
        }
    }
    return;
}

把这个写成函数之后,每次调用就可以了,也就是说,处理第step+1个盒子的方法就是dfs(step + 1)

void dis(int step)
{
    for(int i = 1; i <= n ; ++i)
    {
        //判断球是否被放过
        if(book[i] == 0)//说明i号球没有被放过
        {
            a[step] = i;将第i号球放到第step个盒子里
            book[i] = 1;
            dfs(step + 1);//函数递归调用
            book[i] = 0;//这一步非常重要。必须将球收回才能进行下一步
        }
    }
    return;
}

还有最后一个问题,如何判断一次排列结束了呢

if(step == n + 1)//如果站在第n + 1个盒子前,表示前n个盒子已经放好球了
{
    for(int i = 1; i <= n ; ++i)//输出一种排列
        cout << a[i] 
        cout << endl;
        return ;
}

下面就是整体代码:

#include<iostream>
using namespace std;
int a[10];
int flag[10];
int n;
void dfs(int step)
{
    if(step == n + 1)
    {
        for(int i = 1 ; i <= n;i++ )
            cout << a[i] << " " ;
        cout << endl;
        return;
    }
    for(int i = 1 ; i <= n ; i++)
    {
        if(flag[i] == 0)
        {
        a[step] = i;
        flag[i] = 1;
            dfs(step + 1);
            flag[i] = 0;
        }

    }
    return;
}
int main()
{
    cin >> n;
    dfs(1);

    return 0;
}

dfs的基本模型:

void dfs(int step)
{
判断边界
    {
        继续下一步dfs(step + 1);
    }
}

猜你喜欢

转载自blog.csdn.net/ancientear/article/details/79702567