DFS——剪枝

news2025/7/18 18:44:30

文章目录

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

概述

优化搜索顺序

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

例:
给定一个无重复元素的数组 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. 剪枝
    除了上面提到的可行性剪枝,本题值得注意的是等效冗余剪枝

在这里插入图片描述

总结

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

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

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

相关文章

JavaSE第6篇:面向对象上

一、面向对象 1、面向对象&#xff1a;人关注对象、人关注具体事物信息 2、对象: 只要是客观存在的事物皆为对象 面向对象程序设计的重点是类的设计 设计类就是设计类的成员 思考&#xff1a;人把大象装进冰箱 ? 面向过程POP思想&#xff1a;强调的是过程&#xff08;动…

Web前端开发入门学习分享

Web前端开发入门学习分享 1&#xff1a;如何开始学习Web前端 首先你需要学习html的各个标签&#xff0c;掌握其用法和规范&#xff0c;明白其作用。 开始学习css的使用&#xff0c;你先学习在html页面中为标签增加css样式&#xff0c;其次是将css写在网页的<head></…

【记录】chmod修改组属性失效问题

记录一次chmod命令修改文件夹失效问题。 1.问题描述 有一个普通用户的目录test权限是750&#xff0c;使用chmod将文件权限修改成770发现同组的其他用户无法在该目录创建文件。 2.问题原因 给目录设置acl权限导致chmod在修改文件权限时失效【其实不是失效了】 调研发现&#…

超1.58亿人将“血拼”,超级星期六购物节即将到来

超1.58亿人将“血拼”&#xff01;美国超级星期六购物节即将到来&#xff01;亚马逊出手整治“远仓近送”&#xff01;据美国零售联合会的年度消费者调查结果显示&#xff0c;在今年圣诞节前的最后一个星期六&#xff08;即超级星期六&#xff09;&#xff0c;将有1.58亿人发生…

集成滤波器的5G大规模天线的S参数测试方法

【摘 要】集成滤波器的5G大规模天线由于每个通道包含了一组滤波器,使得5G大规模天线的通道之间的幅度和相位一致性指标变得很差,进一步地,使得获取除滤波器以外的纯通道之间的幅度和相位的一致性指标变得非常困难。对集成滤波器的5G大规模天线的测试方法进行了原理分析和实…

postgresql及wal2json插件安装

1、安装postgres 安装文档见&#xff1a;https://www.postgresql.org/download/linux/redhat/ 我这里是centos7系统&#xff0c;选择安装postgresql11 # Install the repository RPM: sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_…

有什么办法把录音转成文字?这几种方法一看就会

大家在平时工作中是否经常会遇到录音转文字的时候&#xff0c;如果我们一边听一边记的话&#xff0c;有可能会漏掉一些内容&#xff0c;然后就需要暂停或者重听&#xff0c;这样既费时费力还会降低我们的工作效率。这个时候我想应该会有小伙伴觉得&#xff0c;要是录音能直接变…

高通 OpenXR SDK 使用指南(1)

高通 OpenXR SDK 使用指南&#xff08;1&#xff09;1 OpenXR 概述1.1 加载器1.2 运行时1.3 API层1.4 合成器1 OpenXR 概述 OpenXR 是一个免版税的框架&#xff0c;可以访问 AR、VR 和 MR 平台和设备。 在 OpenXR 之前&#xff0c;不同的供应商构建了自己的专有 SDK 来支持 XR…

四、Jetson Xavier Nx内置16G emmc刷机、CUDA、SSD启动

1 刷机 注意JETSON Xavier NX DEV KIT 搭配的是官方16eMMC版本的Jetson Xavier NX 16GB/8GB 核心板&#xff0c;不带SD卡卡槽。因此烧录系统需要用到ubuntu 18.04主机&#xff0c;使用SDK Manager工具烧录。 烧录环境&#xff1a; Ubuntu18.04 主机 &#xff08;虚拟机也可以&…

CS5518芯片规格书|CS5518设计参数|MIPI转LVDS转换方案芯片设计规格书

CS5518是一个MIPI DSI输入、LVDS输出转换芯片。MIPI DSI支持多达4个局域网&#xff0c;每个通道以1Gbps的速率运行。LVDS支持18位或24位像素&#xff0c;通过VESA或JEIDA格式。它只能使用单个1.8V电源&#xff0c;以节省成本并优化电路板空间。 CS5518适用于多个细分市场和显…

TCP半关闭状态分析和skynet对半关闭状态的支持

TCP半关闭状态分析一、背景二、TCP四次挥手流程三、发送FIN包的场景四、skynet 网络封装支持半关闭状态4.1、连接的建立4.2、连接断开4.3、消息到达4.4、消息发送完毕五、测试skynet对半关闭的支持5.1、测试直接关闭进程5.2、测试关闭读端5.2、测试关闭写端总结后言一、背景 T…

经典设计模式总则

Design pattern 设计模式背景-概念、面向对象六大原则、设计模式分类、二十三中常用设计模式即创建型模式、结构型模式、行为型模式 1、设计模式的背景、概念及其必要性 1.1、设计模式的背景 设计模式最初并不是应用于软件设计领域&#xff0c;而是被用于建筑领域的设计中。 …

圣诞节送哪款电容笔合适?平价电容笔排行

随着技术的发展&#xff0c;各种品牌的电容笔也随之出现。一款出色的电容笔可以极大地提升我们的工作效率&#xff0c;并改善我们的学习方式。就目前的技术而言&#xff0c;平替电容笔无论从质量还是性能上都是物有所值的&#xff0c;其表现与苹果的原装电容笔相差无几。下面就…

谈谈vue的路由守卫和keep-alive后生命周期

目录 &#x1f53d; Vue-Router的懒加载如何实现 1、方案一&#xff1a;箭头函数import 2、方案二&#xff1a;箭头函数require 3、方案三&#xff1a;箭头函数require.ensure &#x1f53d; 如何定义动态路由 param方式 query方式 &#x1f53d; Vue-Router导航守卫 …

美颜sdk背景扭曲修复算法的实现流程

目前&#xff0c;美颜sdk在对人像进行美型美体等编辑处理的时候&#xff0c;想要保证背景不受影响&#xff0c;是比较困难的&#xff0c;如果需要在手机端上进行处理&#xff0c;难度更大&#xff0c;主要有以下几点&#xff1a; 一、难点分析 1、拍摄背景多变&#xff0c;背景…

反向迭代器reverse_iterator模拟实现

准备工作 相同的命名空间可以分割在不同的文件中,编译器最后都会合成在同一个命名空间下。我们的reverse_iterator是个适配器&#xff0c;为什么叫适配器&#xff0c;是因为它需用正向迭代器做适配。简言之&#xff0c;反向迭代器通过正向迭代器做实例化会减少很多冗余且方便很…

基于Fragstats的土地利用景观格局分析

景观格局及相关软件介绍 Fragstats界面与数据格式 数据准备&#xff1a;ArcGIS软件操作 数据准备&#xff1a;数据结构及变换 数据准备&#xff1a;数据投影及变换 数据准备&#xff1a;数据采集与编辑 数据准备&#xff1a;数据获取及处理 土地利用统计分析 Fragstats…

微服务(一) —— 概念

目录1. 什么是微服务2. springcloud3. 服务提供者、服务消费者1. 什么是微服务 微服务&#xff1a; 分布式架构的一种。 服务集群&#xff1a;将一个功能复杂的项目拆分成许多个独立的项目&#xff08;称为服务&#xff0c;每部分完成一定的功能&#xff09;&#xff0c;并进…

继承、多态、组合(Java系列5)

目录 前言&#xff1a; 1.继承 1.1继承的概念 1.2继承的语法 1.3父类成员访问 1.4super关键字 1.5super和this 1.6继承关系的执行顺序 1.7继承方式 1.8final关键字 2.继承与组合 3.多态 3.1多态的概念 3.2多态实现的条件 4.重写 4.1重写的概念 4.2方法重写的规…

前端基础(十五)_多栏布局(两列自适应布局、圣杯布局---三列布局、双飞翼布局--三列布局、等高布局)

什么是自适应&#xff1f; 自适应&#xff1a;让同一个页面自动适应不同大小的设备&#xff0c;从而解决为不同设备提供不同版本页面的问题。 自适应布局&#xff1a;解决在不同大小的设备上呈现相同网页的问题 两列自适应布局 1、Html结构中–左右两个盒子&#xff1b; 2、…