剪枝总结

article/2025/9/16 1:47:36

一、引子

剪枝,就是减小搜索树规模、尽早排除搜索树中不必要的分支的一种手段。

形象地看,就好像剪掉了搜索树的枝条,故被称为剪枝。

二、常见剪枝方法

1.优化搜索顺序

在一些问题中,搜索树的各个分支之间的顺序是不固定的

不同的搜索顺序会产生不同的搜索形态,规模也相差甚远

2.排除等效分支

在搜索过程中,如果我们能够得知搜索树的当前节点沿着

某几条不同分支到达的子树是等效的,那么只需要对其中

一条路径进行搜索

3.是否可行剪枝

在搜索过程中,每次对当前状态进行检查,如果发现不可

能到达递归边界,就执行回溯

4.最优性剪枝

在求解最优解的过程中,如果当前解已经没有当前最优解

优秀,此时可以执行回溯语句

5.记忆化剪枝

记录每个状态的搜索结果,在重复遍历一个状态时返回

三、例题

(一)生日蛋糕 POJ1190

题目描述

Mr.W 要制作一个体积为Nπ 的 M层生日蛋糕,每层都是一个圆柱体。设从下往上数第 i蛋糕是半径为 Ri,高度为 Hi 的圆柱。当 i<Mi<M 时,要求Ri>Ri+1且Hi>Hi+1。由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 Q最小。 令 Q=Sπ ,请编程对给出的 N和M ,找出蛋糕的制作方案(适当的 Ri 和Hi 的值),使 S最小。(除 QQ 外,以上所有数据皆为正整数)

输入

第一行为 N ,表示待制作的蛋糕的体积为Nπ; 

第二行为 M ,表示蛋糕的层数为 M 。 

输出

输出仅一行,一个整数 S(若无解则 S=0 )。

样例输入

100
2

样例输出

68

提示

附:圆柱相关公式:体积 V=πR2H;侧面积 S’=2πRH;底面积 S=SπR2。

数据范围与提示

对于全部数据,1≤N≤104,1≤M≤20。 

题解:

搜索框架:从下往上搜索,枚举每层的半径和高度作为分支

搜索状态:第dep层,当前外表面积s,当前体积v,dep+1层的高度和半径

整个蛋糕的底面积=最底层的圆面积,这样在m-1层搜索时,只需要计算侧面积

剪枝:

1.是否可行剪枝

首先枚举R\epsilon [dep,min(\sqrt{N-v},r[dep+1]-1)]

其次枚举H\epsilon [dep,min(\sqrt{N-v}/R^{2},h[dep+1]-1)]

2.优化搜索顺序

倒序搜索枚举

3.可行性剪枝

预处理最小体积和侧面积,然后剪枝

#include <bits/stdc++.h>
using namespace std;
int n,m;
int ans=2e9;
void dfs(int dep,int s,int v,int past_r,int past_h)
{if(s >= ans) return;if(dep == m+1 && v == n){ans = min(ans,s);return;}if(v >= n) return;int rest_dep = m - dep + 1;if(rest_dep * past_r * past_r * past_h + v < n) return;if(dep == 1){for(int r = past_r; r >= m; --r)for(int h = m; h <= past_h; ++h)dfs(dep + 1,s + r * r + 2 * r * h,v + r * r * h,r,h);}else{for(int r=past_r-1; r>=m-dep+1; --r)for(int h=m-dep+1; h<past_h; ++h)dfs(dep + 1,s + 2 * r * h,v + r * r * h,r,h);}
}
int main()
{scanf("%d%d",&n,&m);dfs(1,0,0,28,28);if(ans == 2e9) printf("0\n");else printf("%d\n",ans);
}

(二)Sticks POJ1011

题目描述

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。 

输入

第一行为一个单独的整数N表示砍过以后的小木棍的总数。 第二行为 N个用空格隔开的正整数,表示N根小木棍的长度。

输出

输出仅一行,表示要求的原始木棍的最小可能长度。

样例输入

9
5 2 1 5 2 1 5 2 1

样例输出

6

提示

数据范围与提示

1≤N≤60

题解:

我们可以从大到小枚举原始木棒的长度len.而len应该是sum的约数

原始木棒的根数cnt=sum/len

对于枚举的每个len,我们可以依次搜索每根原始木棒由哪些木棍组成

搜索顺序:从大到小

搜索状态:正在拼的木棍序号、木棒长度、现在拼好的长度、现在拼好的木棒根数

剪枝

1.优化搜索顺序

从大到小排序,优先尝试长的木棍

2.排除等效分支

(1).因为先拼一根a长度的,再拼一根b长度的等于

先拼一根b长度的,再拼一根a长度,只要搜索其中一种

(2).记录最近一次尝试拼接的木棍长度,如果搜索失败则不尝试

同种长度的木棍

(3).当尝试拼入的第一根木棍就返回失败,则直接回溯

(4).如果当前木棍拼入后,一节木棒被填充完整,而另一根木棍

失败了,则直接回溯

代码:

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,sum=0,a[MAXN];
bool vis[MAXN]; 
int cmp(int a,int b)
{return a>b;
}
bool dfs(int num,int len,int now_len,int number)
{if(number==sum/len)return 1;if(now_len==len){if(dfs(1,len,0,number+1))return 1;}for(int i=num; i<=n; i++){if(!vis[i]&&now_len+a[i]<=len){vis[i]=true;if(dfs(i+1,len,now_len+a[i],number))return 1;vis[i]=false;if(a[i]==len-now_len||now_len==0)break;while(a[i]==a[i+1])i++; }}return 0;
}
int main()
{memset(vis,false,sizeof(vis));scanf("%d",&n);for(int i=1; i<=n; i++){scanf("%d",&a[i]);sum+=a[i];}sort(a+1,a+1+n,cmp);for(int i=a[1]; i<=sum; i++){if(sum%i!=0)continue;if(dfs(1,i,0,0)){cout<<i<<endl;break;}}
}

 

 


http://chatgpt.dhexx.cn/article/rmfiWlpC.shtml

相关文章

搜索剪枝

目录 什么是剪枝 几种常见的剪枝 1.可行性剪枝 2.排除等效冗余 3.最优性剪枝 4.顺序剪枝 5.记忆化 运用实例 1.选数 2.吃奶酪 3.小木棍 什么是剪枝 剪枝&#xff1a;通过某种判断&#xff0c;避免一些不必要的遍历过程。搜索的时间复杂度通常很大&#xff0c;通过剪…

【模型压缩】(二)—— 剪枝

一、概述 剪枝&#xff08;Pruning&#xff09;的一些概念&#xff1a; 当提及神经网络的"参数"时&#xff0c;大多数情况指的是网络的学习型参数&#xff0c;也就是权重矩阵weights和偏置bias&#xff1b;现代网络的参数量大概在百万至数十亿之间&#xff0c;因此…

环形队列的基本运算算法-数据结构教程

环形队列的基本概念 如图&#xff0c;其实它就是一个队列&#xff0c;就是有点难理解而已&#xff0c;它避免了普通队列的缺点&#xff0c;一样有队列头&#xff0c;队列尾&#xff0c;一样是先进先出的原则。我们采用顺时针的方式来对队列进行排序。 队列头(front) :允许进行删…

一道亚马逊算法面试题的情景分析

阅读博客的朋友可以观看视频&#xff1a; http://study.163.com/course/courseMain.htm?courseId1002942008 我们聚焦于一道亚马逊的算法面试题&#xff0c;通过分析该题&#xff0c;复盘它的解题情景&#xff0c;我们可以初步体会到算法面试的应对步骤&#xff0c;并从中窥…

LeetCode刷题笔记 标准模板库巧解算法题 优先队列

优先队列简介 ​ 优先队列&#xff08;priority queue&#xff09;可以在 O(1) 时间内获得最大值&#xff0c;并且可以在 O(log n) 时间内取出最大值或插入任意值。 ​ 优先队列常常用堆&#xff08;heap&#xff09;来实现。堆是一个完全二叉树&#xff0c;其每个节点的值总…

Python数据结构与算法(3.4)——队列相关应用与习题

Python数据结构与算法(3.4)——队列相关应用与习题 0. 学习目标1. 使用两个栈实现一个队列2. 使用两个队列实现一个栈3. 栈中元素连续性判断4. 重新排列队列中元素顺序5. 反转队列中前 m 个元素的顺序相关链接0. 学习目标 我们已经学习了队列的相关概念以及其实现,同时也了…

第十七章 优先队列优化Dijkstra算法

第十七章 优先队列优化Dijkstra算法 一、普通dijkstra算法的缺陷1、选出最小距离的过程&#xff1a;2、松弛所有点的过程&#xff1a; 二、如何优化1、代码模板&#xff08;1&#xff09;问题&#xff1a;&#xff08;2&#xff09;模板&#xff1a; 2、详细解读 三、优化分析1…

【自顶向下模块化编程】C语言实现多级反馈队列调度算法

自顶向下-多级反馈队列 多级反馈队列算法算法原理算法描述题目摘要 自顶向下模块化设计整体框架具体实现GeneratorSchedulerExecutor 整体代码实现 总结及心得总结心得 多级反馈队列算法 多级反馈队列调度算法是一种CPU处理机调度算法&#xff0c;UNIX操作系统采取的便是这种调…

[算法] 栈和队列

欢迎来到老胡的算法解题思路&#xff0c;本文章主要使用的语言为java&#xff0c;使用的题型为力扣算法题&#xff0c;基于这一篇文章&#xff0c;我将为你介绍栈和队列的基础知识和栈和队列的题型&#xff0c;喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#xff01; 目…

十道经典面试算法真题详解

前言 分享一下 腾讯常考的十道算法题&#xff08;真题&#xff09;。在金三银四&#xff0c;希望对大家有帮助呀。 重排链表 最长递增子序列 环形链表 反转链表 最长回文子串 全排列 LRU 缓存 合并K个升序链表 无重复字符的最长子串 删除链表的倒数第 N 个结点 1. …

队列相关习题

1.已知循环队列存储在一维数组A0…n-1]中&#xff0c;且队列非空时front和rear分别指向队头元素和队尾元素。若初始时队列为空&#xff0c;且要求第一个进入队列的元素存储在A[0]处&#xff0c;则初始时front和rear的值分别是( )。 A.0&#xff0c;0 B. 0&#xff0c;n-1 C. n-…

java算法面试题_Java算法面试题汇总

原标题&#xff1a;Java算法面试题汇总 1. 字符串 如果IDE没有代码自动补全功能&#xff0c;所以你应该记住下面的这些方法。 toCharArray() // 获得字符串对应的char数组 Arrays.sort() // 数组排序 Arrays.toString(char[] a) // 数组转成字符串 charAt(int x) // 获得某个索…

详解单调队列算法

前言 嘿!彩蛋!感觉有帮助就三连呗! 如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 在上一篇文章中,我们介绍了「单调栈」这一最常考察的线性数据结构。而今天我们将继续沿着这个思路,介绍另…

栈和队列相关经典算法题总结(数据结构+C语言)

我们这里针对栈和队列的一些经典算法题做详细讲解: 1.括号匹配问题. 2.用队列实现栈. 3.用栈实现队列. 4.设计循环队列. 一.详细讲解如下: 1.括号匹配问题.(如下图) 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &am…

qt使用消息队列服务器,qt代码实现消息队列通信

qt代码实现消息队列通信 内容精选 换一换 HBase 1.X版本在RPC流程中&#xff0c;多个数据通信线程会争抢同一个缓存Buffer队列&#xff0c;代码以lock重入锁实现线程安全&#xff0c;锁抢占严重&#xff0c;导致HBase不能充分发挥CPU多核的能力。HBase 1.X版本的RPC通信机制中B…

消息队列MQ常见面试题

面试官在面试候选人时&#xff0c;如果发现候选人的简历中写了在项目中使用了 MQ 技术&#xff08;如 Kafka、RabbitMQ、RocketMQ&#xff09;&#xff0c;基本都会抛出一个问题&#xff1a;在使用 MQ 的时候&#xff0c;怎么确保消息 100% 不丢失&#xff1f; 这个问题在实际…

RabbitMQ消息队列常见面试题总结

1、什么是消息队列&#xff1a; 1.1、消息队列的优点&#xff1a; &#xff08;1&#xff09;解耦&#xff1a;将系统按照不同的业务功能拆分出来&#xff0c;消息生产者只管把消息发布到 MQ 中而不用管谁来取&#xff0c;消息消费者只管从 MQ 中取消息而不管是谁发布的。消息…

【消息队列】面试题及答案整理

消息队列面试题 为什么要使用消息队列/消息队列的应用场景使用了消息队列会有什么缺点如何保证消息队列是高可用的RocketMQ是如何保证消息队列是高可用的 如何保证消息不被重复消费/如何保证消息消费的幂等性如何保证消费的可靠性传输RocketMQ如何保证消费的可靠性传输RabbitMQ…

JAVA——快速排序(详细)

JAVA快速排序的实现 快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高&#xff0c;因此经常被采用&#xff0c;再加上快速排序思想----分治法也确实实用&#xff0c;因此很多软件公司的笔试面试&#xff0c;包括像腾讯&#xff0c;微软等知名IT公司都喜欢考这个&…

快速排序算法(java实现)

基本思想 快速排序是一种采用分治法解决问题的一个典型应用&#xff0c;也是冒泡排序的一种改进。它的基本思想是&#xff0c;通过一轮排序将待排记录分割成独立的两部分&#xff0c;其中一部分均比另一部分小&#xff0c;则可分别对这两部分继续进行排序&#xff0c;已达到整…