DFS深搜


前言

忘带课本了,记一下课本上的内容,不然等还书就忘记了。


深度优先搜索

输入一个数n,输出1~n的全排列。转换成模型就是编号1,2,3的扑克牌放到1,2,3的盒子中去,每个盒子只放一张牌,一共有多少种不同的放法。我们先走到1号盒子前面,规定从1号扑克牌依次放入,所以把1号扑克牌放进1号盒子,然后走到2号盒子前面。按照规定的顺序,2号扑克牌放在2号盒子,3放3号盒子。此时生成了一种排列就是“1,2,3”。然后开始返回。走到第三个盒子,拿出3号牌,但是手上只有三号牌,没有其他选择,所以不放新的牌,再走到2号盒子拿出2号牌,此时手里有2,3号牌,我们选择3号放入2号盒子,2号放入3号盒子,此时又生成了一个新的排列“1 3 2”如此循环下去,我们能够得到所有的排列。

代码如下(示例):

//用一个for循环就可以解决
for (i = 1; i <= n; i++) {
	a[step] = i;//将i号扑克牌放入第step个盒子中
}

比如说1号已经放入盒子中,那么下次放扑克牌的时候就不能再放1号了,因为手里已经没有1号牌了。因此我们应该用一个数组book来标记已经使用过的扑克牌

for (i = 1; i <= n; i++) {
	if(book[i]==0) {//扑克牌还没有被使用
	a[step] = i;//将i号扑克牌放入第step个盒子中
	book[i] = 1;//此时手里已经没有这张牌了
	}		
}

我们已经处理完这step个盒子了,继续往下是第step+1个盒子,此时设置一个函数,用递归调用此函数即可

void DFS(int step) //step表示现在站在的第几个盒子面前
{
  for (i = 1; i <= n; i++) {
	if(book[i]==0) {//扑克牌还没有被使用
	a[step] = i;//将i号扑克牌放入第step个盒子中
	book[i] = 1;//此时手里已经没有这张牌了
	DFS(step + 1);//递归调用DFS函数
	book[i] = 0;//非常关键的一步,只用把用过的扑克牌先收回来,才能继续使用
	}
}
  return;	
}

我们发现,当处理到第n+1个盒子时,前面n个盒子已经全部处理完毕,此时将扑克牌的编号打印出来即可。注意:打印完毕要立即return,不然就没法重新调用DFS函数了

void DFS(int step) //step表示现在站在的第几个盒子面前
{
	if (step == n + 1)//表示现在站在第n+1个盒子面前,前面n个盒子已经放好了
	{
		//输出一种排列
		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;//将i号扑克牌放入第step个盒子中
	book[i] = 1;//此时手里已经没有这张牌了
	DFS(step + 1);//递归调用DFS函数
	book[i] = 0;//非常关键的一步,只用把用过的扑克牌先收回来,才能继续使用
	}
}
  return;	
}

完整代码

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

void DFS(int step) //step表示现在站在的第几个盒子面前
{
	int i;
	if (step == n + 1)//表示现在站在第n+1个盒子面前,前面n个盒子已经放好了
	{
		//输出一种排列
		
		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;//将i号扑克牌放入第step个盒子中
	book[i] = 1;//此时手里已经没有这张牌了
	DFS(step + 1);//递归调用DFS函数
	book[i] = 0;//非常关键的一步,只用把用过的扑克牌先收回来,才能继续使用
	}
}
  return;	
}
int main()
{
	scanf_s("%d", &n);//注意输入1到9之间的整数
	DFS(1);//首先站在1号盒子面前
	getchar();
	getchar();
	return 0;
}

总结

这个例子是深度优先搜索(Depth First Search,DFS)的基本模型。
关键在于解决现在该干什么,这就需要用到递归调用。
基本模型如下:

void DFS(int step)
{
	判断边界
		尝试每一种可能 for (i = 1; i <= n; i++)
	{
		继续下一步 DFS(step + 1);
	}
	返回
}

每一种尝试就是一种“扩展”。每一次站在一个盒子面前的时候,其实都有n种扩展方法,但并不是每种扩展方法都能成功。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值