深度优先搜索

深度优先搜索

        事实上,深度优先搜索属于图算法的一种,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。

举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束)。

图

下面我们有一个例子来分析其过程:

假如有编号为1,2,3,的3张扑克牌和编号为1,2,3的3个盒子。现在需要将这3张扑克牌分别放到3个盒子里面,并且每个盒子有且只能放一张扑克牌。那么一共有多少种不同的放法呢?

我们现在来解决最基本的问题:如何往小盒子里放扑克牌。每个小盒子都有可能放1号,2号或者3号扑克牌,这需要一一去尝试,这里一个for循环就可以解决。

for(i = 1; i <= n; i ++)
{
	a[step] = i;//将i号扑克牌放入第step个盒子 
}

这里数组a是用来表示小盒子的,变量step表示当前正处于第step个小盒子面前。这里有一个问题就是,如果一张扑克牌已经放到别的小盒子中了,那么此时就不能再放入同样的扑克牌到当前小盒子中,因为此时手中已经没有那张扑克牌了。因此,还需要一个数组book来标记哪些牌已经使用了。

for(i = 1; i <= n; i ++)
{
	if(book[i] == 0)//book[i]等于0表示i号扑克牌仍然在手上 
	{
		a[step] = i; 
		book[i] = 1;//将book[i]设为1,表示i号扑克牌已经不在手上了 
	}
} 

OK,现在已经处理完第step个小盒子了,接下来需要往下走一步,继续处理第step+1个小盒子。那么如何处理第step+1个小盒子呢?处理方法其实和我们刚才处理step是一样的。因此就可以想到把刚才的处理第step个小盒子的代码封装为一个函数,dfs函数。

void dfs(int step)//step表示现在站在第几个盒子面前 
{
	for(i = 1; i <= n; i ++)
	{
		if(book[i] == 0)
		{
			a[step] = i;
			book[i] = 1;
		}
	}
	return 0;
}

把这个过程写成函数后,刚才的问题就好办了。在处理完第step个小盒子之后,紧接着处理第step+1个小盒子,处理step+1个小盒子的方法就是dfs(step+1),请注意下面代码标记的语句。

void dfs(int step)
{
	for(i = 1; i <= n; i ++)
	{
		if(book[i] == 0)
		{
			a[step] = i;
			book[i] = 1;
			dfs(step+1);//这里通过函数的递归调用来实现(自己调用自己)
			book[i] = 0;// 这是非常重要的一步 ,一定要将刚才尝试的扑克牌收回,
			//才能进行下一次尝试
		}
	}
	return 0;
}

还剩下一个问题,什么时候该输出一个满足要求的序列呢。其实当我们处理到第n+1个小盒子的时候(即step等于n+1),那么说明前n个盒子都已经放好扑克牌了,这里将1到n个小盒子中的扑克牌编号输出就可以了。

void dfs(int step)
{
	if(step == n+1)
	{
		for(i = 1; i <= n; i ++)
			printf("%d",a[i]);
		printf("\n");
		return ;//返回之前的一步(最近一次调用dfs函数的地方) 
	}
	for(i = 1; i <= n; i ++)
	{
		if(book[i] == 0)
		{
			a[step] = i;
			book[i] = 1;
			dfs(step+1);//这里通过函数的递归调用来实现(自己调用自己)
			book[i] = 0;// 这是非常重要的一步 ,一定要将刚才尝试的扑克牌收回,
			//才能进行下一次尝试
		}
	}
	return 0;
}

完整代码

#include<stdio.h>
int a[10],book[10],n;

void dfs(int step)
{
	int i;
	if(step == n+1)
	{
		for(i = 1; i <= n; i ++)
			printf("%d",a[i]);
		printf("\n");
		return ;
	}
	for(i = 1; i <= n; i ++)
	{
		if(book[i] == 0)
		{
			a[step] = i;
			book[i] = 1;
			dfs(step+1);
			book[i] = 0;
		}
	}
	return ;
}
int main()
{
	while(scanf("%d",&n) != EOF)
	{
		dfs(1);//首先站在1号小盒子面前 
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值