搜索
DFS简介
搜索算法:
穷举问题解空间部分/所有情况,从而求出问题的解
深度优先搜索:
本质上是暴力枚举
深度优先:尽可能一条路走到底,走不了再回退
DFS和n重循环
给定一个数字x,将其拆分成3个正整数,后一个要求大于等于前一个,给出方案。
简单思想:三重循环暴力求解
那么,拆分成4个正整数?n个正整数呢?
需要实现n重循环
n重循环 = 特定的树状结构 = DFS搜索
给定一个数字x=6,将其拆分成3个正整数,后一个要求大于等于前一个,给出方案。
给定一个数字x,将其拆分成n个正整数,后一个要求大于等于前一个,给出方案。
n重循环:n层的树
DFS:从上往下找一条合法的路径(路径值不递减,长度为n,和为x
def dfs(depth):
"""
:param depth: 当前是第几重循环
:return:
"""
global cnt
cnt = cnt + 1
if depth == n:
for i in range(1,n):
if a[i] >= a[i-1]:
continue
else:
return
if sum(a) != x:
return
print(a)
return
for i in range(1,x+1):
a[depth] = i
dfs(depth+1)
x , n = map(int,input().split())
a = [0] * n
cnt = 0
dfs(0)
print("累计计算次数={}".format(cnt))
把条件放在枚举的时候判断可以降低计算量:剪枝
def dfs(depth,last_val):
global cnt
if depth == n:
if sum(a) != x:
return
print(a)
return
for i in range(last_val,x+1):
a[depth] = i
dfs(depth+1,i)
x , n = map(int,input().split())
a = [0] * n
cnt = 0
# dfs(0)
dfs(0,1)
print("累计计算次数={}".format(cnt))
例题
题目链接:4124分糖果
ans = 0
def dfs(depth,n,m):
"""
:param depth:第depth个小朋友
:param n: 第一类糖果数量
:param m: 第二类糖果数量
:return:
"""
if depth == 7:
if n == 0 and m == 0:
global ans
ans += 1
return
for i in range(0,6):
for j in range(0,6):
if 2 <= i+j <= 5 and i <= n and j <= m:
dfs(depth+1,n-i,m-j)
dfs(0,9,16)
print(ans)
运行结果
5067671
题目链接:3505买瓜
def dfs(depth,s,cnt):
"""
:param depth: 第depth层循环
:param s: 当前累计的重量
:param cnt: 当前劈的西瓜个数
:return:
"""
if s > m :
return
if s == m :
global ans
ans = min(ans,cnt)
if depth == n:
return
#买一个
dfs(depth + 1 , s + w[depth] , cnt)
# 买半个
dfs(depth + 1, s + w[depth] // 2, cnt+1)
# 不买
dfs(depth + 1, s, cnt)
n , m = map(int,input().split())
m *= 2
w = list(map(int,input().split()))
w = [x * 2 for x in w]
ans = n+1
dfs(0,0,0)
if ans == n+1:
ans = -1
print(ans)
运行结果
3 10
1 3 13
2