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 dfs(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 dfs(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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值