深度优先搜索(DFS)

本文介绍了二叉树的先序、中序和后序遍历,并通过示例解释了递归实现斐波那契数列的方法。接着,展示了如何使用深度优先搜索(DFS)进行全排列生成,以及在一个迷宫搜索问题中的应用。通过这些实例,深入理解了DFS在解决递归和搜索问题中的基本模型和策略。
摘要由CSDN通过智能技术生成

我们先来看一下二叉树的遍历

如图二叉树,那么他的先序遍历中序遍历后序遍历分别为多少呢?

1、先序遍历(根左右

先序遍历的结果为:2 7 1 6 5 3 8 9 4

2、中序遍历(左根右

中序遍历的结果为:1 7 5 6 3 2 8 4 9

3、后序遍历(左右根

后序遍历的结果是:1 5 3 6 7 4 9 8 2

导引问题:从递归说起

斐波那契数列的定义大家都非常熟悉:

F(0)=1;

F(1)=1;

F(n)=F(n-1)+F(n-2);

斐波那契数列的递归实现

//首先分析问题的“递归特征”——除了规模,其它一样
int fibonacci(int a)
{
    // 先写出口(不需递归的特殊情况)
    if(a==0 || a==1)
        return 1;
    else
        return fibonacci(a-1)+fibo(a-2); // 再写普通情况(递归)
}

下面看一个具体的例子:

输入一个正整数n,请按照字典序输出1-n的全排列,每个排列输出一行,每个数字后面跟一个空格。

Sample Input

3

Sample Output

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

思路:

——如果第1个数确定(比如1),剩余的问题就是其余n-1个数的全排列;

——如果前k个数已经排好,剩余的问题就是其余n-k个数的全排列!

解题代码

#include<bits/stdc++.h>
using namespace std;

int n;
int num[10],vis[10];
void dfs(int step);

int main()
{
	while(scanf("%d",&n)==1);
	{
		memset(vis,0,sizeof(vis));
		dfs(1);
	}
	return 0;
}

void dfs(int step){
	if(step == n+1){
		for(int i=1;i<=n;i++)
			printf("%d",num[i]);
		printf("\n");
		return;
	}
	for(int i=1;i<=n;i++){
		if(vis[i]==0){
			num[step]=i;
			vis[i]=1;
			dfs(step+1);
			vis[i]=0; // 回溯 
		}
	}
}

深度优先搜索的基本模型

深度优先搜索的关键在于解决“当下该如何做”!

至于下一步怎么做,则与当前一样(只是参数不同而已)

深度优先搜索的基本模型:
void dfs(int step)
{

        特殊情况处理(一般是结束递归的情况)

        枚举当前每一种可能for(i=1;i<=n;i++)

                在枚举的每一种可能中,递归dfs(step+1);

}

再来看一个例子:

解题代码

典型的迷宫搜索!!!

#include<bits/stdc++.h>
using namespace std;
char Map[9][9];
int n,m,t,di,dj;
bool escape;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
void dfs(int si,int sj,int cnt);

int main()
{
	int i,j,si,sj;
	while(cin>>n>>m>>t)
	{
		if(n==0 && m==0 && t==0)
			break;
		int wall=0;
		for(i=1;i<=n;i++)
			for(j=1;j<m;j++)
			{
				cin>>Map[i][j];
				if(Map[i][j]=='S')
				{
					si=i;sj=j;	
				}
				else if(Map[i][j]=='D')
				{
					di=i;dj=j;
				}
				else if(Map[i][j]=='X')
				wall++;
			}
			if(n*m-wall<=t)
			{
				cout<<"NO"<<endl;
				continue;
			}
			escape=0;
			Map[si][sj]='X';
			dfs(si,sj,0);
			if(escape)
				cout<<"YES"<<endl;
			else
				cout<<"NO"<<endl; 
	}
	return 0;
}

void dfs(int si,int sj,int cnt)
{
	int i,temp;
	if(si>n || sj>m || si<=0 || sj<=0)
		return;
	if(cnt==t && si==di && sj==dj)
		escape=1;
	if(escape)
		return;
	temp=(t-cnt)-abs(si-di)-abs(sj-dj);
	if(temp<0 || temp%2==1)
		return;
	for(i=0;i<4;i++)
	{
		if(Map[si+dir[i][0]][sj+dir[i][1]]!='X')
		{
			Map[si+dir[i][0]][sj+dir[i][1]]='X';
			dfs(si+dir[i][0],sj+dir[i][1],cnt+1);
			Map[si+dir[i][0]][sj+dir[i][1]]='.';
		}
	}
	return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值