dfs通常与“递归+循环”一起使用,所以要以“递归”的眼光去遍历所有可能的方案或者路径。
1. 一个问题的解可以分解为若干个子问题的解,即存在某种递归公式。
2.递归的终止条件。
3. 翻译成递归代码。
除此之外,为了避免重复计算,可以利用数组来保存过去已经计算好的值,在下一次使用时直接调用即可;该方法称之为“记忆性递归”。
其相比简单的递归,可以减少时间复杂度,本质是用空间换时间。
【第五届:地宫取宝】
1. 递归公式
——选
或
——不选
2. 终止条件
已经到达出口,
①若拿到的宝物数满足数量,则返回 1,路径存在;②否则,返回 0,路径不存在。
3. 代码
n, m, k = map(int, input().split())
mp = [list(map(int, input().split())) for i in range(n)]
# 记忆性缓存,提高函数递归时的性能
from functools import lru_cache
@lru_cache(maxsize=None)
def dfs(x, y, z, w): # z: 先前拿的宝物数量 w: 先前拿的宝物的最大价值
if x == n-1 and y == m-1:
if z == k:
return 1
if z == k - 1 and w < mp[x][y]:
return 1
return 0
ans = 0
# (dx, dy)=(1,0):向右走 (dx, dy)=(0,1):向下走
for dx, dy in [(1, 0), (0, 1)]:
# 每个位置可有两个选择 更新坐标
nx = x + dx
ny = y + dy
if nx < n and ny < m:
# 总次数为选择+不选择
ans += dfs(nx, ny, z, w) # 当前不选择宝物,走到 (nx,ny)
if w < mp[x][y]: # 当前选择宝物,走到 (nx,ny)
ans += dfs(nx, ny, z + 1, mp[x][y])
ans %= 10 ** 9 + 7
return ans
print(dfs(0, 0, 0, -1))
【第十四届:分糖果】
1. 递归公式
2. 终止条件。
糖果已经分给了7个人,
①所有糖果都分完了,该路径存在;②否则,该路径不存在。
3. 代码。
def dfs(numOne, numTwo, numPeople):
# 分的人数够7人了,说明分完了
if numPeople == 7:
if numOne==0 and numTwo==0:
return 1
return 0
ans = 0
for j in range(numOne+1): #第一种糖果
for k in range(numTwo+1): #第二种糖果
if j+k >=2 and j+k <= 5:
ans += dfs(numOne-j,numTwo-k,numPeople+1)
return ans
print(dfs(9, 16, 0))
【第十四届:飞机降落】
1. 递归公式。
2. 终止条件。
所有的飞机都能够顺利着陆,则成功;并不需要飞机着陆的方案。
3. 代码。
# a代表飞机数,b代表当前时间
def dfs(a, b):
# 设置为全局变量
global flag
if a==n: #如果飞机能开到n+1架,说明已经成功
flag = True
return
if flag:
return
for i in range(n):
if visited[i]==0:
if t[i]+d[i]<b:
flag = False
return
visited[i] = 1
dfs(a+1, max(b,t[i])+l[i])
visited[i] = 0
n = int(input())
# 防止越界
t=[0]*15
d=[0]*15
l=[0]*15
for i in range(n):
# 输入每组数据
groupNum = int(input())
word = 1
for j in range(groupNum):
# 每架飞机的 降落时刻区间 & 落地时刻区间
t[j], d[j], l[j] = map(int, input().split())
# 标记所有的飞机安全降落
flag = False
visited = [0]*15
dfs(0,0)
if flag:
print("YES")
else:
print("NO")
【第十四届:异或和】
1. 递归公式。
若该结点仍有子结点,则继续深度搜索。
2. 终止条件。
到底叶子结点处。
3. 代码。
import sys
def dfs(pos):
global ans
# 终止条件:叶子结点
if relations[pos]==[]:
return
for t in relations[pos]:
ans ^= weighted[t]
dfs(t)
# 输入数据
n, m = map(int, input().split())
weighted = [0] + [x for x in map(int, input().split())]
relations = [[] for _ in range(n+1)]
for i in range(n-1):
i, j = map(int, input().split())
if i<j:
relations[i].append(j)
else:
relations[j].append(i)
for i in range(m):
info = [int(x) for x in input().split()]
if info[0]==1:
weighted[info[1]] = info[-1]
elif info[0]==2:
ans = weighted[info[1]]
dfs(info[1])
print(ans)