DFS——剪枝优化迭代加深

news2025/4/12 5:00:17

文章目录

        • 概述
          • 优化搜索顺序
          • 排除等效冗余
          • 可行性剪枝
          • 最优性剪枝
        • 例题
          • 小猫爬山
          • 木棒
        • 迭代加深
          • 概述
          • 加成序列
        • 总结

概述

优化搜索顺序

不同的搜索顺序会产生不同的搜索树形态,与可行性剪枝结合,去除非法状态,按照一定顺序可使规模大幅度减小。

例:
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 : 输入:candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
在这里插入图片描述

可见第二种情况所访问的节点数量小于第一种,顺序的优化时为了尽快的减掉不合法的分支。也就是易于满足可行性剪枝的条件

排除等效冗余

在搜索过程中,如果我们能够判定从搜索树的当前节点上沿着某几条不同分支到达的子树是等效的,那么只需要对其中一条分支进行搜索。
一种是组合还是排列问题,如果是组合那么就上面的例题而言[1, 2]和[2, 1]是一种效果
其次就是路径选择时,前一个选择的路径和当前选择的路径效果相同,且前一个路径搜索失败,那么如果按照当前路径走的话效果相同,故可跳过。例如上题,搜索[2, 4, 4, 5]目标时7,如果搜索到第一个4,发现失败跳过后,搜索第二个失败状态也是一样的。如果成功的话对于组合数来说也是同等效果。

可行性剪枝

在搜索过程中,及时对当前状态进行检查,如果发现分支已经无法到达递归边界(非法),就执行回溯。
常见的剪枝是“上下界剪枝”

最优性剪枝

在最优化问题的搜索过程中,如果当前花费的代价已经超过了当前已经搜到的最优解,那么无论采取多么优秀的策略到达递归边界,都不可能更新答案。此时可以停止搜索,执行回溯。

例题

小猫爬山

翰翰和达达饲养了 N 只小猫,这天,小猫们要去爬山。

经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<)。

翰翰和达达只好花钱让它们坐索道下山。

索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1、C2……CN。

当然,每辆缆车上的小猫的重量之和不能超过 W。

每租用一辆缆车,翰翰和达达就要付 1 美元,所以他们想知道,最少需要付多少美元才能把这 N 只小猫都运送下山?

输入格式
第 1 行:包含两个用空格隔开的整数,N 和 W。

第 2…N+1 行:每行一个整数,其中第 i+1 行的整数表示第 i 只小猫的重量 Ci。

输出格式
输出一个整数,表示最少需要多少美元,也就是最少需要多少辆缆车。

数据范围
1≤N≤18,
1≤Ci≤W≤108
输入样例:
5 1996
1
2
1994
12
29
输出样例:
2

  1. 搜索顺序
    搜索每一个小猫,考虑小猫放到已有的缆车中还是新开一个缆车。
    终点:搜索完最后一个小猫,所以需要一个参数cur表示当前搜索的是第几只猫
    路径选择:新开一个缆车或是在已有缆车中选择,所以需要一个参数u表示已经开好的缆车
    所以参数def dfs(u, cur)

  2. 代码

N = 20

cab = [0] * N
cats = []
ans = N

def dfs(u, cur) :
	global ans
	if ans <= u : #最优性剪枝
		return
	if cur == n : 
		ans = u
		return
	
	cab[u] = cats[cur] #开一个新缆车
	dfs(u + 1, cur + 1)
	cab[u] = 0
	for i in range(u) :
		if cab[i] + cats[cur] <= m :#可行性剪枝
			cab[i] += cats[cur]
			dfs(u, cur + 1)
			cab[i] -= cats[cur]
			
n, m = map(int, input().split())
for i in range(n) : 
	t = int(input())
	cats.append(t)

cats.sort(reverse = True) #优化搜索顺序

dfs(0, 0)
print(ans)
  1. 剪枝的操作
    if cab[i] + cats[cur] <= m :#可行性剪枝,对应于可行性剪枝,缆车的承重有一定限制,那么从大到小搜索质量可以尽快的去处不合法的分支
木棒

乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过 50 个长度单位。

然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。

请你设计一个程序,帮助乔治计算木棒的可能最小长度。

每一节木棍的长度都用大于零的整数表示。

输入格式
输入包含多组数据,每组数据包括两行。

第一行是一个不超过 64 的整数,表示砍断之后共有多少节木棍。

第二行是截断以后,所得到的各节木棍的长度。

在最后一组数据之后,是一个零。

输出格式
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

数据范围
数据保证每一节木棍的长度均不大于 50。

输入样例:
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
输出样例:
6
5

  1. 搜索顺序
    枚举木棒长度,因为,木棍是由所有长度相等的木棒砍断而来,所以只有当木棒长度可以整除木棍长度之和,才可行。
    枚举能被木棍长度之和整除的木棒长度。假如此时枚举的长度为length,搜索木棍的组合,考虑木棍的组合的和是否等于length。如果相等,则除去当前搜索组合中的木棍,并记录木棒个数,从剩余木棍中搜索组合和为length的木棍。如果不相等则失败。搜索直到木棒的个数*length等于木棍长度之和为止
    终点:木棒的个数u * length等于木棍长度之和
    路径选择:组合数,需要有搜索的木棍的位置start
    可行性 : 当前组合之和cur + 枚举到木棍长度

  2. 代码

N = 70

def dfs(u, cur, start) :
	if length * u == cal : return True
	if cur == length : return dfs(u + 1, 0, 0)

	i = start
	while i < n :
		if not st[i] and cur + sticks[i] <= length : #可行性剪枝
			st[i] = True
			if dfs(u, cur + sticks[i], i + 1) : return True
			st[i] = False
			if not cur or cur + sticks[i] == length : return False #排除首尾冗余
			j = i + 1
			while j < n and sticks[i] == sticks[j] : j += 1 #排除路径冗余
			i = j - 1
		i += 1
			

while True :
	n = int(input())
	if n == 0 : break
	st = [False] * N
	sticks = list(map(int, input().split()))
	sticks.sort(reverse = True) # 优化搜索顺序
	cal = sum(sticks)
	length = 1
	while True :
		if cal % length == 0 and dfs(0, 0, 0) :
			break
		length += 1
	print(length)
  1. 剪枝
    除了上面提到的可行性剪枝,本题值得注意的是等效冗余剪枝

在这里插入图片描述

迭代加深

概述

深度优先搜索每次都是选定一个分支,不断深入,直至到达递归边界才回溯。但是这种策略带有一定的缺陷。试想以下情况:搜索树每个节点的分支数目非常多,并且问题的答案在某个较浅的节点上。如果深搜一开始选错了分支,就很可能在不包含答案的深层子树上浪费许多时间。
如下图是问题的状态空间,五角星标识着答案:
在这里插入图片描述
那么深度优先搜索算法产生的搜索树就如下图所示,该算法在矩形圈出的深层子树上浪费了很多时间。
在这里插入图片描述
此时,我们可以从小到大限制搜索的深度,如果在当前深度限制下搜索不到答案,就把搜索深度限制增加,扩大一层,然后重新进行一次搜索,这就是迭代加深的思想。所谓"迭代",就是以上一次的结果为基础,重复执行以逼近答案。

迭代加深DFS的过程如下:
在这里插入图片描述
总之,当搜索树的规模随着层次的深入增长很快,并且我们能够确保答案在一个较浅的节点时,就可以采用迭代加深DFS的方法。某些题目描述"若10步以内搜不到结果就算无解",对于这种题目,可以大胆用迭代加深DFS算法。

加成序列

满足如下条件的序列 X(序列中元素被标号为 1、2、3…m)被称为“加成序列”:

X[1]=1
X[m]=n
X[1]<X[2]<…<X[m−1]<X[m]
对于每个 k(2≤k≤m)都存在两个整数 i 和 j (1≤i,j≤k−1,i 和 j 可相等),使得 X[k]=X[i]+X[j]。
你的任务是:给定一个整数 n,找出符合上述条件的长度 m 最小的“加成序列”。

如果有多个满足要求的答案,只需要找出任意一个可行解。

输入格式
输入包含多组测试用例。

每组测试用例占据一行,包含一个整数 n。

当输入为单行的 0 时,表示输入结束。

输出格式
对于每个测试用例,输出一个满足需求的整数序列,数字之间用空格隔开。

每个输出占一行。

数据范围
1≤n≤100
输入样例:
5
7
12
15
77
0
输出样例:
1 2 4 5
1 2 4 6 7
1 2 4 8 12
1 2 4 5 10 15
1 2 4 8 9 17 34 68 77

  1. 搜索策略:
    依次搜索序列中每个位置k,枚举i和j作为分支,把X[i] + X[j]的和填到X[k]上,然后递归填写下一个位置

  2. 代码

N = 110
path = [0] * N

def dfs(u, k) :
	if u == k : return path[u - 1] == n
	st = [False] * N #去除等效冗余
	for i in range(u - 1, -1, -1) :
		for j in range(i, -1, -1) :
			s = path[i] + path[j]
			if s > n or s <= path[u - 1] or st[s] : continue #可行性剪枝
			st[s] = True
			path[u] = s
			if dfs(u + 1, k) : return True
	return False

while True :
	n = int(input())
	if n == 0 : break
	path[0] = 1
	depth = 1
	while not dfs(1, depth) : depth += 1 #迭代加深
	for i in range(depth) :
		print(path[i], end = " ")
	print()

总结

一般题目都会有可行性剪枝,其他几个如何剪枝需要依据题意进行剪枝。

当搜索树的规模随着层次的深入增长很快,并且我们能够确保答案在一个较浅的节点时,就可以采用迭代加深DFS的方法。某些题目描述"若10步以内搜不到结果就算无解",对于这种题目,可以大胆用迭代加深DFS算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/109733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新能源电池进入高速发展阶段,数商云S2B2C商城赋能企业分销渠道管理更便捷

在国家政策扶持下&#xff0c;我国新能源汽车市场飞速发展&#xff0c;产品供给不断丰富、企业创新活力竞相迸发、使用环境日臻完善以及消费者认可度日益提高&#xff0c;近年来更是产销两旺&#xff0c;新能源汽车产销量屡创新高&#xff0c;作为新能源车的核心部件——电池&a…

面试官问我 ,try catch 应该在for循环里面还是外面?

前言 有个老哥昨天被面试官欺负了&#xff0c;但是是被这个问题&#xff08;标题&#xff09;欺负的&#xff1f; 其实是个比较基础的问题&#xff0c;只要有了解过&#xff0c;叙述是非常简单OK的。 只要有初学者觉得有疑惑&#xff0c;那么我相信不止是他一个。 所以&#…

青少年等级考试【Python通关干货】(一级)

青少年等级考试【Python通关干货】&#xff08;一级&#xff09; 1. 编程模式 1&#xff09;交互式编程 在交互式环境的提示符>>>下&#xff0c;直接输入代码&#xff0c;按回车&#xff0c;就可以立刻得到代码执行结果。 交互式编程缺憾是没有保存下来&#xff0c;下…

2023 目标,与君共勉

新的一年&#xff0c;立一些目标&#xff0c;与君共勉 技术相关目标 csdn申请专业领域创作认证通过、博客专家认证通过掘金创作等级可以达到LV6等级掘金发表两个小册&#xff0c;有50人以上订阅csdn原先的进阶专栏&#xff0c;增加到100篇文章&#xff0c;有50人以上订阅csdn…

2021地理设计组一等奖:面向游客的旅游路线优化设计——以丹霞山景区为例

作品简介 一、背景与意义 随着旅游业的快速发展与人们对旅行质量要求的提升&#xff0c;旅游者对旅游服务的内容要求也越来越高&#xff0c;其中的旅游导航便是一项需求率极高的服务。然而传统的导航服务多是基于时间或距离成本进行网络分析而提供的路径设计&#xff0c;极少考…

R16 Dormant BWP

微信同步更新欢迎关注同名modem协议笔记 接上篇BWP结尾&#xff0c;R15时SCell的激活和去激活是通过Pcell的MAC CE&#xff0c;R16在Scell上引入dormant BWP的概念&#xff0c;可以通过DCI 控制Scell在dormant BWP和non-dormant BWP间进行切换&#xff0c;相比于MAC CE的控制方…

SpringBoot 基于 OAuth2 统一身份认证流程详解

1. 目标 了解OAUTH2统一认证基本概念了解OAUTH2协议流程了解OAUTH2各种模式类型了解Spring Security OAuth设计 2. 分析 传统登陆认证介绍 单点登陆认证介绍 OAuth2简介 OAuth2角色 OAuth2协议流程介绍 OAuth2授权类型 OAuth2授权码模式流程 OAuth2简化模式 OAuth2密码…

JavaScript 入门基础 / 概念介绍(一)

JavaScript 入门基础 / 概念介绍&#xff08;一&#xff09; 1.初识JavaScript 1.1 JavaScript历史 1995年&#xff0c;网景公司一名程序员布兰登艾奇利用十天完成了JavaScript设计&#xff0c;网景公司最初将它命名为LiveScript&#xff0c;后与Sun公司合作将其改名为JavaS…

外行人如何通过学习软件测试转行IT

随着互联网的快速发展&#xff0c;现在很多行业都被智能化取代&#xff0c;IT行业从业人员剧增&#xff0c;很多不是IT行业的人都想转行IT&#xff0c;那么对于不是IT行业的人&#xff0c;如何能快速转行变成IT人呢&#xff1f;软件测试是你最好的选择。对于一个不是本行业的人…

内科大深度学习期末复习笔记

文章目录一.选择判断1.1矩阵与 神经网络模型 与 深度学习模型 关系1.2 机器学习 与 深度学习 在训练数据中的区别1.3点乘与叉乘区别1.4 深度学习模型 浅层与深层 关系1.5线性关系与非线性 权重和偏置1.6 超参数&#xff08;训练数据与可调整数据&#xff08;var&#xff09;&am…

10年经验hr亲授:刷完阿里P8架构师的RocketMQ核心手册,进大厂稳了

为什么要选择RocketMQ? 市场上几大消息队列对比如下&#xff1a; 总结一下&#xff1a; 选择中间件的可以从这些维度来考虑&#xff1a;可靠性&#xff0c;性能&#xff0c;功能&#xff0c;可运维行&#xff0c;可拓展性&#xff0c;社区活跃度。目前常用的几个中间件&…

基于容器的PaaS混合云的几种形式

概述 这是 Gartner 的一个图&#xff0c;提供了全球的基于容器的 PaaS 公有云、混合云服务的梳理展示&#xff1a; 这里提供一个其他的视角&#xff1a; 中国市场&#xff0c;基于容器的 PaaS 混合云&#xff08;公有云 私有云&#xff09;的相关厂商及产品。 ❗️ 注意&am…

PyTorch笔记 - Batch\Layer\Instance\Group\Weight Normalization 源码

欢迎关注我的CSDN:https://blog.csdn.net/caroline_wendy 本文地址:https://blog.csdn.net/caroline_wendy/article/details/128416962 Normalization in NN: Batch Normalization: per channel across mini-batchtorch.nn.BatchNorm1d / torch.nn.BatchNorm2dLayer Normaliz…

2023世界杯新媒体传播热点盘点 中国元素之中国馆、富而喜悦!

2022年卡塔尔世界杯于上周日落幕&#xff0c;作为“后新冠时代”的首个大型全球体育赛事&#xff0c;也同时被多个“史上首次”与“历史之最”所装点。作为普通球迷亦或资深网友的你&#xff0c;对本届世界杯的流行趋势与媒体热点有多少了解呢&#xff1f;富而喜悦&#xff0c;…

RISCV-V-1.0向量扩展指令集学习

大部分内容翻译自 riscv-v-spec-1.0 部分参考&#xff1a; 【《RISC-V “V“ Vector Extension Version 1.0》阅读笔记】_LPL之芯的博客-CSDN博客 RISC-V “V”(向量)扩展规范v0.9文档&#xff08;2&#xff09; - 知乎 (zhihu.com) 文章目录3. Vector Extension Programmers M…

开放下载丨2023年二十万字技术年货新鲜送达

文章目录一、再谈数字化二、关于技术合集三、思想沉淀与书写价值四、写在最后一、再谈数字化 21世纪是无可争议的数字时代。过去20多年来&#xff0c;中国企业踏上了一个伟大而又艰难的数字化转型征程。虽然在行业数字化转型的深度和广度方面&#xff0c;头部企业已经相当领先…

IU酒店打造齐鲁文化旅游发展新高地

淄博&#xff0c;位处鲁中&#xff0c;是黄河三角洲生态经济和蓝色经济区的交汇处。四季分明的气候造就了这座齐国故都的生态多样性&#xff0c;南高北低的地理位置使其峻岭平原兼具&#xff0c;鲁中的位置又赋予他交通枢纽的重要性。这里历史气息浓厚&#xff0c;社会文化自由…

@SuppressWarnings使用-屏蔽一些无关紧要的警告

SuppressWarnings 用法 与idea设置相关-参考 作用&#xff1a;用于抑制编译器产生警告信息&#xff0c;不显示波浪提示线。 我们在写代码的时候&#xff0c;不论是导入的包&#xff0c;还是声明的对象&#xff0c;有时候会出现黄线&#xff0c;感觉就很难受&#xff01; Su…

TensorFlow性能分析调研

文章目录背景&#xff1a;一、tensorflow的训练模式2.2.1 with tf.profiler.experimental.Profile(logdir,optionsoptions):背景&#xff1a; 进行性能分析的过程中&#xff0c;不可避免地在训练的过程中加入相关语句&#xff0c;以输出相应的日志文档&#xff0c;方便后续的性…

作为码农的我,要怎么提高自己的收入?

打工人是不是都会想同一个问题&#xff1a;我怎么赚大钱&#xff1f; 作为码农的我&#xff0c;实在不知道该如何提高自己的收入&#xff0c;首付凑不齐房子买不了&#xff0c;生活怎么样才能过的更好一些&#xff1f; 今天&#xff0c;就来说说&#xff0c;作为程序员&#…