DFS
深度优先遍历(DFS)也叫深度优先搜索。它的定义是:不断地沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。
深度优先搜索 也可以说是 递归 ,在代码的实现中主要是利用函数调用自己,那么学习 深度优先搜索 的主要前置知识就是手写 函数 ,属于非常简单且基础的一种可以成为算法的东西,而其时间复杂度通常不低,在一些题目中可以获得部分分,代码方面也好写,所以也可以在 对拍 时候使用。
举个题做例子:
超级书架
题目描述
Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留有一点空间。
所有
N
(
1
<
=
N
<
=
20
)
N(1 <= N <= 20)
N(1<=N<=20)头奶牛都有一个确定的身高
H
i
(
1
<
=
H
i
<
=
1
,
000
,
000
H_i(1 <= H_i <= 1,000,000
Hi(1<=Hi<=1,000,000- 好高的奶牛>_<)。设所有奶牛身高的和为S。书架的高度为
B
B
B,并且保证
1
<
=
B
<
=
S
1 <= B <= S
1<=B<=S。
为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。
为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。
塔叠得越高便越不稳定,于是奶牛们希望找到一种方案,使得叠出的塔在高度不小于书架高度的情况下,高度尽可能小。你也可以猜到你的任务了:写一个程序,计算奶牛们叠成的塔在满足要求的情况下,最少要比书架高多少。
输入格式
第
1
1
1行:
2
2
2个用空格隔开的整数:
N
N
N和
B
B
B第
2..
N
+
1
2..N+1
2..N+1行: 第
i
+
1
i+1
i+1行是
1
1
1个整数:
H
i
H_i
Hi
输出格式
第
1
1
1行: 输出
1
1
1个非负整数,即奶牛们叠成的塔最少比书架高的高度_
样例数据
input
5
16
3
1
3
5
6
output
1
注释
输出说明:
我们选用奶牛1、3、4、5叠成塔,她们的总高度为3 + 3 + 5 + 6 = 17。任何方案都无法叠出高度为16的塔,于是答案为1。
数据规模与约定
时间限制:1s
空间限制:256MB
分析
这就需要搞个递归,在递归里枚举每头牛,分出两种情况:这头牛取还是不取。
这里的函数首先需要两个变量:第几头牛,高度。
编不下去了, 放代码
#include <bits/stdc++.h>
using namespace std;
int k , da = 999999 , ans , h , p;//用da来记录高于书架的最低高度
int a[10086];
void sj(int m,int n)
{
if(n >= h && da > n) da = n;//如果高度高于书架且低于其他方法,更新da
if(m > k) return; //递归中很重要的一点就是找到边界,不然无限循环
sj(m + 1 , n); //这头牛不往上摞
sj(m + 1 , n + a[m]); //这头牛往上摞
}
int main()
{
cin >> k >> h;
for(int i = 1 ; i <= k ; i ++)
{
cin >> a[i]; //第i头牛的高度
}
sj(0 , 0); //一开始的时候用了0头牛,高度为0
cout << da - h; //输出高度差
return 0;
}
有时候如果输不出东西,要检查边界是否设置得当
注:
有人(也可能只有我)会怀疑,递归中的
void sj(int m,int n)
在其中多次使用,是否会相互干扰。
肯定不会啊!!!
看图说话。
可以理解为倒二叉树
把最左的一个枝干砍掉们不会影响其他几根枝干。
而在
r
e
t
u
r
n
return
return后,会继续运行其他树杈。
就是这么一个进栈出栈的过程。
而 深度优先搜索 其实很有可能搜索到相同的情况,那么在一些题目中我们可以做一个 桶 来作记录,这样的方法也可以被称为 记忆化搜索