深度优先搜索DFS详解2(非常详细,容易理解)

13 篇文章 0 订阅

之前的文章我已经讲过一次DFS了,这次呢就是DFS的两种用法了

第一部分 图的深搜

看到这里很多人会问:图?图上次不是讲过了吗?

没错,但是这次的图指的是一种数据结构,而不是那种二维数组迷宫什么的了。

这里简单展示一张图:

1
2
3
4
5

这是一个有向图。

那我们怎么存储它呢?

用一个数组。

如何存储?

首先定义二维数组a

bool a[10][10];

这个数组代表什么呢?
代表两个点之间是否有联系,比如a[1][2]=true,a[1][3]=false
注意由于这是一个有向图,所以a[2][1]=false
下面展示一个无向图

1
2

可以看到他们互相指着

当然,无向图一般不画箭头,连线即可

读入图

一边看代码一边解释。

int n,m;//n,m分别是点的个数和边的个数,记得定义成全局变量
bool a[10][10];//路径数组,记得定义成全局变量
cin >> n >> m;
for(int  i = 1; i <= n; i++){
	int x,y;//两个点
	cin >> x >> y;
	a[x][y]=true;
	//如果是无向图的话,就是a[x][y]=a[y][x]=true,表示都有联系
}

如何DFS

题目很多样化,要看具体情况dfs,但都是一个模板。

有时候路径还会有长度,这时候a数组要定义成int类型。

这里给出模板。

假设题目是:求两点是否相通

bool vis[10];//代表第u个节点是否搜过
bool dfs(int u){//dfs(u)代表目前正在搜索u号节点
	if(u==end)return true;//是终点就返回true
	bool flag=false;//这里定一个flag
	vis[u]=1;//这个节点搜过了
	for(int i = 1; i <= n; i++){
		if(a[u][i]==1){//这两个节点是否相通?
			if(vis[i])continue;//搜过了就continue
			bool t=dfs(i);//否则搜这个点
			flag=flag|t;//这里用到了位运算,只要flag和t有一个是true,flag就是true
			//这里可以加一个优化,判断如果flag==true,就直接返回
		}
	}
	return flag;
}

这个部分的 结语 废话

累死我了,这个部分就写完了,请大家支持一下,点个赞什么的,虽然很累吧,但是能帮助更多人的话,累也值得。我已经写了 1170 1170 1170个字了,按这个节奏下去,我恐怕得写 2000 2000 2000

好的废话不多说,我们开始下一部分

全排列问题

这是一个经典的dfs问题
题目是:

输入 n n n,输出 1 1 1 n n n的全部排列方法

排列是什么玩意

如果你知道什么是排列,可以跳过此部分

首先我们得先了解什么是排列

排列用符号 A A A表示, A n m A^m_n Anm表示从 n n n个数里面选择 m m m个数进行排列

排列是有序的,比如1,2,3和1,3,2是不同的排列

A n m A^m_n Anm表示从 n n n个数里面选择 m m m个数进行排列的个数

比如 A 3 2 = 6 A^2_3=6 A32=6

1 2
1 3
2 1
2 3
3 1
3 2

顺带提一下排列个数公式:
A n m = n × ( n − 1 ) × ( n − 2 ) × ⋅ ⋅ ⋅ × ( n − m + 1 ) A^m_n=n\times(n-1)\times(n-2)\times ··· \times (n-m+1) Anm=n×(n1)×(n2)××(nm+1)

全排列

就是 A n n A_n^n Ann
表示 n n n个数的全部排列方法

怎么写

其实很简单,定义一个vis数组,表示这个数用过了没。

上代码。

bool vis[10];
int a[10];//排列方法
void dfs(int u){//dfs(u)表示选择第u个数
	if(u>n){//选完了
		for(int i = 1; i <= n; i++){
			cout << a[i] << " ";//输出
		}
		cout << endl;
		return;
	}
	for(int i = 1; i <= n; i++){
		if(!vis[i]){//每用过
			a[u]=i;//这个位置设置为i
			vis[i]=1;//用过了
			dfs(u+1);//选下一个数
			vis[i]=0;//回溯,把这个设为没用过
			//a[u]不用管,下次递归自动覆盖
		}
	}
}

结语废话

好的那么这从的DFS讲完了,在这里投个票,下次讲什么

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值