【Acwing167】木棒(dfs+剪枝)超级详细题解!

题目描述

 统一说明

本题思路来源于acwing算法提高课

木棍指题目输入数据所指的东西

木棒指最后由木棍拼接而成的最长的东西

看本文需要准备的知识

1.dfs基本思想

2.对“剪枝”这个词汇有一个基本的认识即可

整体分析

这个题目最终是求木棒的最短长度,所以我们可以从长度为1开始,每次加一,一直往后搜索,当搜索到解时,必然是最短长度。而在搜索的过程当中,显然长度满足:sum%length==0,这也是本题的一个小优化,dfs参数说明:

dfs(u,cur,start)

u:当前已经拼接好几根木棒

cur:当前正在拼接的这跟木棒已经拼好的长度

start:对同一根木棒,从哪一根木棍开始遍历

剪枝优化

A.优化搜索顺序

1.为了优先搜索分支较少的节点,我们可以让木棍按长度由大到小排序,优先搜索长度最长的木棍

B.排序等效冗余

1.按照组合数方式枚举,就是给每个木棍编号,有序的遍历,防止出现同一个木棒中由“1,2,3”拼成和“3,2,1”拼成的两种分支情况,毕竟一个木棒是如何拼成的跟木棍的顺序无关,所以对于同一根木棒拼接的时候,可以设置一个下标start,每次遍历木棍的时候从start开始遍历,即dfs(u,cur+w[i],start+1)

2.如果当前木棍加到某个木棒上之后失败了,那么跟这个木棍相同长度的木棍加到这个位置的时候也会失败

C.可行性剪枝

1.如果一个木棍放在某一个木棒的第一个位置时失败了,那么就没有遍历剩下的木棍放在这个位置的必要了,也就是说这时候我们需要回溯了,什么意思呢,我用递归树的方式带领大家理解:

比如说A是在木棒x+1的第一个位置上放置木棍1,如果A的子树向A传递了false,那么接下来的路径就不是:“从A通过a回溯到D再通过b进入B”而是“直接通过a回溯到D再通过d回溯到E了”,其中B是在木棒x+1的第一个位置上放置木棍2,C同理,D是在木棒x的最后一个位置上放置某一个木棍

如何证明上述的剪枝的正确性呢?反证法

假设在木棒x的第一个位置上放木棍1失败,但往后继续搜索还能发现最终的正确方案,那么这个木棍1,一定会被放置在后续木棒的某个位置上,假设这个木棒是p,这个位置是n,这时候,我们可以把木棒p上的第一个位置的木棍和n位置上的木棍1交换,然后再把木棒x和木棒p做一个位置交换,发现:此时木棒x的第一个位置上放的是木棍1!!!与假设矛盾,证毕

2.如果一个木棍1放在一个木棒x的最后一个位置,并且可以使这个木棒的最长度达到length,但是在这个状态节点的子树给这个节点返回了false,那么就可以直接向上面一样,在回溯到D之后直接回溯到E,而不是进入B!

证明:反证法

假设在满足上述情况下,还可以找到某一个或多个木棍的拼接使得木棒x拼成length,此时木棍1一定在下面的某一个木棒的某一个位置中,我直接把木棍1和x此时后面为length长度的一个或几个木棍的拼接对换,就会发现:木棍1放在木棒x的最后一个位置,并且可以使这个木棒的最长度达到length!!!与假设矛盾,证毕

想说的话

感觉这题确实有点抽象,特别是可行性剪枝的两个部分,所以我采用了从递归树的角度,从底层,分析了这个问题,如果有没有看懂的或者我错了的地方,拜托各路大佬在评论区指出,谢谢!

满分代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=70;
int w[N];
int sum,length;
bool st[N];
int n;bool dfs(int u,int cur,int start)
{if(u*length==sum)return true;if(cur==length)return dfs(u+1,0,0);for(int i=start;i<n;i++){if(st[i]||cur+w[i]>length)continue;st[i]=true;if(dfs(u,cur+w[i],start+1))return true;st[i]=false;if(!cur||w[i]+cur==length)return false;int j=i+1;while(j<n&&w[i]==w[j])j++;i=j-1;}return false;
}int main()
{while(cin>>n,n){memset(st,false,sizeof st);sum=0;for(int i=0;i<n;i++)cin>>w[i];for(int i=0;i<n;i++)sum+=w[i];sort(w,w+n);reverse(w,w+n);length=1;while(true){if(sum%length==0&&dfs(0,0,0)){cout<<length<<endl;break;}length++;}}return 0;
}

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

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

相关文章

shell脚本的基础知识

目录 1.什么是shell 2.shell脚本的意义 3.如何创建shell脚本 4.如何执行shell脚本 5.如何对脚本进行测试 脚本练习 1.什么是shell Shell是一种命令行解释器&#xff0c;是用户与操作系统内核之间的接口&#xff0c;允许用户编辑和执行命令。它是用户输入命令并将其传递给操…

万能鼠标设置 SteerMouse v5.6.8

鼠标可谓是用户们在使用电脑时候的必备外接设备呢&#xff01;适合你自己的鼠标设置也绝对能够优化你的Mac使用体验&#xff01;想要更好的Mac体验就试试用Steermouse Mac版吧。它通过软件来自由设置你的鼠标操作&#xff01;在这款万能鼠标设置工具中&#xff0c;用户可以在偏…

Tuxera NTFS2024破解版本下载

当您获得一台新 Mac 时&#xff0c;它只能读取 Windows NTFS 格式的 USB 驱动器。要将文件添加、保存或写入您的 Mac&#xff0c;您需要一个附加的 NTFS 驱动程序。Tuxera 的 Microsoft NTFS for Mac 是一款易于使用的软件&#xff0c;可以在 Mac 上打开、编辑、复制、移动或删…

hdlbits系列verilog解答(模块按名字)-22

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 此问题类似于模块。您将获得一个名为的 mod_a 模块&#xff0c;该模块按某种顺序具有 2 个输出和 4 个输入。您必须按名称将 6 个端口连接到顶级模块的端口&#xff1a; module mod_a ( output out1, output …

FPGA从入门到精通(二十)SignalTapII

这一篇将介绍SignalTapII。 之前的工程我们是做仿真&#xff0c;设置激励&#xff0c;观察输出波形去判断代码没有问题&#xff0c;但事实上我们真实的需求是综合后的代码下载到FPGA芯片中能够符合预期。 其中可能出现问题的原因有&#xff1a; 1、我们是写testbench设置激励…

五、W5100S/W5500+RP2040树莓派Pico<UDP Client数据回环测试>

文章目录 1. 前言2. 协议简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. UDP Client回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 UDP是一种无连接的网络协议&#xff0c;它提供了一种简单的、不可靠的方式来…

软考高级系统架构师冲关预测

[ – 2023年10月27日 – ] 去年11月通过了软考高级系统架构师的考试&#xff0c;原本想立即分享下过关的总结回顾&#xff0c;但是随着软考新版大纲及教程的发布&#xff0c;也意味着题目及内容的复盘总结经验便不那么适用。在即将迎来今年的软考高架的时候&#xff0c;想着透…

构建客户门户的痛点及低代码工具解决方案

企业如何做好数字化转型呢&#xff1f; 如果笼统地说起“数字化转型”&#xff0c;这个概念太大了&#xff0c;它涉及到了企业管理中的方方面面。数字化转型是一个持续不断的过程&#xff0c;既要在整体上进行数字规划&#xff0c;也需要从细节入手&#xff0c;将每一个步骤进…

学习笔记:tarjan

tarjan 引入 Robert Tarjan&#xff0c;计算机科学家&#xff0c;以 LCA、强连通分量等算法而闻名。Tarjan 设计了求解的应用领域的广泛有效的算法和数据结构。他以在数据结构和图论上的开创性工作而闻名&#xff0c;他的一些著名的算法有 Tarjan 最近公共祖先离线算法&#…

一、高效构建Java应用:Maven入门和进阶

一、高效构建Java应用&#xff1a;Maven入门和进阶 目录 一、Maven简介和快速入门 1.1 Maven介绍1.2 Maven主要作用理解1.3 Maven安装和配置 二、基于IDEA的Maven工程创建 2.1梳理Maven工程GAVP属性2.2 Idea构建Maven JavaSE工程2.3 Idea构建Maven JavaEE工程2.4 Maven工程项…

Git Gui使用技巧

资料 https://www.runoob.com/w3cnote/git-gui-window.html 操作过程 创建仓库→添加远程仓库→扫描目录→文件移动→提交→上传 注意填注释 文件忽略 创建文件.gitignore→编写内容 *.log #文件 config.ini #文件 temp/ #目录

什么是恶意代码?

前言&#xff1a;本文旨在分享交流技术&#xff0c;在这里对恶意代码进行全面的介绍和讲解 目录 一.什么是恶意代码 二.恶意代码的发展史 三.恶意代码的相关定义 四.恶意代码攻击机制 PE病毒 PE文件的格式 脚本病毒 脚本文件隐藏方法 宏病毒 浏览器恶意代码 U盘病毒 …

优化改进YOLOv5算法:加入ODConv+ConvNeXt提升小目标检测能力——(超详细)

为了提升无人机视角下目标检测效果,基于YOLOv5算法,在YOLOv5主干中实现了Omnidimensional Convolution(ODConv),以在不增加网络宽度和深度的情况下提高精度,还在YOLOv5骨干网中用ConvNeXt块替换了原始的C3块,以加快检测速度。 1 Omni-dimensional dynamic convolution …

Jenkins 重新定义 pom 内容,打包

文章目录 源码管理构建 源码管理 添加仓库地址&#xff0c;拉取凭证&#xff0c;选择需要的分支 构建 勾选 构建环境 下删除原始 build 配置&#xff0c;防止文件错误 Pre Steps 构建前处理 pom.xml &#xff0c;例如我是需要删除该模块的所有子模块配置&#xff0c;我这里…

面试题之Vue和React的区别是什么?

一提到前端框架&#xff0c;相信大家都对Vue和React不陌生&#xff0c;这两个前端框架都是比较主流的&#xff0c;用户也都比较多&#xff0c;但是我们在使用这些框架的时候&#xff0c;是否对这两个框架之间的区别有所了解呢&#xff1f;接下来&#xff0c;让我们来一起的系统…

vscode下ssh免密登录linux服务器

vscode使用ssh免密登录linux 1、安装SSH插件2、生成密钥3、linux安装ssh服务4、linux下配置公钥5、vscode远程登录 注&#xff1a;测试环境为window10Ubuntu1804/Ubuntu2204 1、安装SSH插件 扩展->搜索SSH->点击install进行安装&#xff0c;如下图所示&#xff1a; 2、…

Docker 容器服务的注册、发现及Docker安全

目录 Docker容器服务的注册和发现 1、什么是服务注册与发现&#xff1f; 2、什么是consul consul的部署 1、环境准备 2、部署consul服务器 1&#xff09;建立 Consul 服务 2&#xff09;设置代理&#xff0c;在后台启动 consul 服务端 3&#xff09;查看集群信息 4&a…

Linux C语言开发-D7D8运算符

算术运算符&#xff1a;-*/%&#xff0c;浮点数可以参与除法运算&#xff0c;但不能参与取余运算 a%b&#xff1a;表示取模或取余 关系运算符&#xff1a;<,>,>,<,,! 逻辑运算符:!,&&,|| &&,||逻辑运算符是从左到右&#xff0c;依次运算&#…

OpenCV学习(三)——响应鼠标事件(获取点击点坐标和颜色,利用鼠标进行绘图)

响应鼠标事件 3. 响应鼠标事件3.1 获取鼠标点击的坐标3.2 获取鼠标点击像素点的颜色3.3 在鼠标点击的位置生成圆3.4 通过拖动鼠标来绘制填充矩形3.5 通过拖动鼠标绘制未填充矩形3.6 使用鼠标选点绘制多边形3.7 按住鼠标左键进行绘图 3. 响应鼠标事件 使用OpenCV读取图像&#…

Virtual DOM

目录 Virtual DOM 前言 用法 代码 理解 Virtual DOM的工作原理&#xff1a; 为什么使用Virtual DOM? 哪些库/框架使用Virtual DOM? 总结 Virtual DOM&#xff08;虚拟DOM&#xff09;是一种编程概念&#xff0c;它是对真实DOM的轻量级抽象表示。在前端开发中&#x…