【思路整理】凑数问题
0.在ExcelHome上遇到很多凑数的贴子,粗略看过香川的代码,用的递归,看不懂,一直觉得这个比较难。春节无事,尝试挑战。
1.研习香川的贴子,花了很长时间,贴子里的解释不多,很费劲,主要是递归绕来绕去就绕晕了,最后发觉根本看不懂,放弃。
2.咨询老同学,点名这东西属于“背包问题”的简化版。
3.网上找了些背包的贴子,绝大多数都只有代码,关于解题思路说的太少,难以理解代码形成的过程。唯一一个有思路的贴子,用的全是数学符号,还是看不懂。
4.心得:看别人的代码比自己写代码还难。
5.不再看别人写的,打算自己硬编。
一、题型
有100张金额不等的发票,期望找到金额为1000元的各张发票的组合。
二、思路
(一)将发票按金额将序排列。
(二)简化问题:只找能够与第一张发票凑成1000的其他发票。
1st.FatherArr=发票集合,包含编号和金额;通过循环,使Arr=小于1000元的发票集合。
2nd.循环Arr,从第一张开始往下加:
1.如果金额小于1000,说明有希望凑成1000,将发票编号记录到临时变量(如ID),金额合计记录到临时变量(如Sum),然后接着加下一个。
按照以上思路再循环一次!
只不过这次目标值变成1000-Sum,Arr是小于1000-Sum的发票集合。
3.1.如果金额小于1000-Sum,说明有希望凑成1000-Sum,将发票编号记录到临时变量(如ID),金额合计记录到临时变量(如Sum2),然后接着加下一个。
3.2.如果金额等于1000-Sum,达成期望,把ID记录到结果数组(如Answer),搞定!
3.3.如果金额大于1000-Sum,失败,说明最后一次把数加冒了。
由于发票是降序排列,后面没准有可以能够与加冒之前凑成1000-Sum的票,但是怎么弄?
按照以上思路再循环一次!
只不过这次目标值变成1000-Sum-Sum2,循环区域变成小于1000-Sum-Sum2的发票集合。
------------------------------------------------------------------------------------------------------------------------
这TM不是圆环套圆环影视城吗,这TM不是递归吗?!这不就行了吗!就是不断的把Contral(i)切割成Contral(i+1),不断的把Arr(i)切割成Arr(i+1)
3rd.回归原问题,按照此方法,再从第二张发票开始往下加,直到全轮一遍。
4th.以上为总体思路,过程中,除了调整Contral的值,另需调整Sum(n);更重要的是切割Arr,并将用过的发票标记出来,从第x张发票开始轮的时候不再使用;在找到期望组合后,相关统计数据初始化。
5th.非常重要的一点:当通过递归1进入了递归2,在递归2完成或Exit Sub后,递归1入口后的代码还要继续执行,并不会因为完成递归N后,所有递归都结束,因此,最后一次递归结束后,无论是否找到期望值,相关统计数据都应当初始化。
(因为这个问题,中间耗费很大精力,一直没搞清楚各种变量是怎么变化的)
6th.过程中可以加点优化效率的代码。
三、代码
Sub Bag()Dim Target: Target = 1000Dim Arr: Arr = Sheets(1).UsedRangeDim r: r = UBound(Arr)Dim Answer: ReDim Answer(1 To r, 1 To 1) '结果标号集合Dim SonArr '每次循环/递归以SonArr为基础,是Arr的子数组Dim C: C = Target 'Contral,每次循环/递归后的目标值,是Target不断变小后形成的目标值;初始值为Target,每次循环后重新设置为TargetDim S: S = 0 'Sum,小于Contral的值临时汇总于该变量;初始值为0,每次循环后重新设置为0Dim ID: ID = "" '小于Contral的值的变号以连接符&拼接后临时存放于该变量;初始值为"",每次循环后重新设置为""Dim k: k = 0 '符合拼凑条件的数的分组标号Dim iFather '循环标签For iFather = 1 To r '循环原理:每次从第r行截取Arr,定义为SonArr;断定SonArr里有没有符合拼凑条件的数。循环/递归过程中会对Arr进行调整,并以新的Arr进行截取。ReDim SonArr(1 To r, 1 To 2)For i = 1 To r - iFather + 1SonArr(i, 1) = Arr(i + iFather - 1, 1)SonArr(i, 2) = Arr(i + iFather - 1, 2)NextCall Dg(SonArr, C, S, ID, Answer, r, k, Arr, Target) '递归;符合拼凑条件的记录进Answer;SonArr\C\S\ID\Arr在递归过程中发生值变动NextWith Sheets(1).Range("D:D").ClearContents.[D1].Resize(r, 1) = AnswerEnd With
End SubSub Dg(mySonArr, myC, myS, myID, theAnswer, r, k, theArr, theTarget)
'MsgBox mySonArr(1, 2) & vbTab & myC & vbTab & myS & vbTab & myIDIf mySonArr(1, 2) = "#" Then Exit Sub '因为循环/递归过程中会对已用过的数以“#”标记,所以循环/递归时,先判断mySonArr第一个值是否为“#”,如果是就跳过去,提高效率Dim Sp, p 'Sp为split-id后形成的数组,p为标号Dim b: b = 0 'Brr实际有效值的数量Dim Brr: ReDim Brr(1 To r, 1 To 2) '剔除大于C后的数的数组t = 0For i = 1 To rIf mySonArr(i, 2) <> "#" And mySonArr(i, 2) <= myC Then '符合条件的mySonArr的值记录进Brr;<注意C值在递归时要调整>;Brr实际有效值的数量为bb = b + 1Brr(b, 1) = mySonArr(i, 1)Brr(b, 2) = mySonArr(i, 2)t = t + Brr(b, 2)End IfNextIf b = 0 Then Exit Sub '如果一个有效值都没有,结束递归If t < myC Then Exit Sub '如果SUM(Brr)<Contral,说明所有值加起来都凑不够目标值,后续代码不必执行,量大时可提高效率For i = 1 To bSelect Case myS + Brr(i, 2) '判定上一次合计值myS与新增值Brr(i, 2)的情况Case Is < myC '如果该值小于Contral,则新增值记录进入myS\myIDmyS = myS + Brr(i, 2)myID = myID & "," & Brr(i, 1)Case myC '如果该值等于Contral,则统计k,结果记录进入Answer,调整theArr,结束递归,临时统计变量初始化myID = myID & "," & Brr(i, 1)k = k + 1Sp = Split(myID, ",")For Each p In SpIf p <> "" ThentheAnswer(Val(p), 1) = ktheArr(Val(p), 2) = "#"End IfNextmyS = 0: myC = theTarget: myID = "": Exit SubCase Is > myC '如果该值大于Contral,则说明值冒了,将myC切割成小号myC,myS清零,并以小号myC再次递归myC = myC - mySmyS = 0Call Dg(Brr, myC, myS, myID, theAnswer, r, k, theArr, theTarget)If myS = 0 And myC = theTarget And myID = "" Then Exit Sub'<!!重要!!>因执行 Is > myC ,从大号递归进入小号递归的情况下,小号递归完成 Case myC 后,仍要返回大号递归继续完成 Is > myC 开始递归后的代码,因此,需要把临时统计数据初始化!并结束递归End SelectNextmyID = "": myC = theTarget: myS = 0 '执行到这里,说明没找到符合条件的拼凑值,因此,初始化临时统计数据,为下一次循环/递归做准备
End Sub
【思路整理】凑数问题相关推荐
- 张铁柱-前端实现《低代码可视化编辑器》(一)思路整理 React-dnd+Ts
张铁柱-前端实现<低代码可视化编辑器>(一)思路整理 React-dnd+Ts 先上效果: 拖拽生成页面+调整顺序 最近,接到任务做一个低代码编辑器,于是着手整理一下思路,调研一下实现方式 ...
- GAN框架研究与思路整理
本文内容将着重分析当前GAN原理及其应用场景,比对其相对于传统深度学习方法在图像生成等方面的区别 一.原始GAN原理 原始GAN论文中的思想为生成模型与判别模型间的零和博弈,通 ...
- VL53L0X 底层思路整理(1)
传感器资料思路整理 世界上最小的飞行时间测距和姿态探测传感器 特点: •完全集成的微型模块 – 940nm激光VCSEL – VCSEL驱动程序 –带有高级嵌入式测距传感器的微控制器 – 4.4 x ...
- C#FFmpeg视频采集与推送RTMP服务器代码思路整理
C#视频采集与推送RTMP服务器代码思路整理:在看过FFmpeg后是否认为写C#的视频流采集和推送还是一头雾水啊?深有此感.领导是C#的高手,说可以通过C或C++的代码直接复制粘贴到C#工程然后进行适 ...
- 多智能体强化学习思路整理
多智能体强化学习算法思路整理 目录 摘要 背景和意义 研究背景 强化学习 多智能体强化学习与博弈论基础 研究意义 问题与挑战 问题分类 问题分析 环境的不稳定性与可扩展性的平衡 部分可观测的马尔可夫决 ...
- 前端实现登录、登出、请求数据的一些思路整理
前端实现登录.登出.请求数据的一些思路整理(基于React.JWT技术) 登录.登出和数据请求是两种不同的数据交互方式,是互相独立的. 登录.登出基于 JWT(JSON WEB TOKEN) 技术,通 ...
- 2018年美国大学生数学建模竞赛原题、翻译及思路整理
参加了2018年的美赛,整理了一些参考资料,需要的话就拿去吧. 具体内容是:2018年美国大学生数学建模竞赛原题.翻译及思路整理,有兴趣的小伙伴可以看看 链接:https://pan.baidu.co ...
- 探索性数据分析的思路整理
探索性数据分析的思路整理 读取数据 清洗数据,对构建的数据进行整理 探索全局特征, 通过直方图,散点图,聚合函数对数据进行全局的了解 探索数据的分组特征,通过分组操作分析数据集 %matplotlib ...
- 华为杯数学建模思路整理
华为杯数学建模思路整理 1.对于题目: 1.1 题目加上使用的模型进行命名,一定要注意字眼和格式:1.2 目录格式,简洁清爽,表现出使用的模型:1.3 别人的东西,加上文献引用;(**)1.4 对于评 ...
- 2021美赛D题艺术家思路整理
问题整理 使用influence_data数据集或其部分创建音乐影响力的(多个)定向网络,其中影响者与关注者相连.开发捕捉此网络中"音乐影响的参数".通过创建定向影响网络的子网络来 ...
最新文章
- ubuntu服务器版编辑文件,Ubuntu 服务器版 18.04.4 固定 IP 设置
- c语言规定标识符 字符串,c语言中标识符命名规则是怎样的
- 如何知道当前像素的顶点坐标_GT 大神 | 如何高效渲染流体效果(绝对干货)
- java我的世界极限生存_我的世界 1.7.10 极限生存整合包
- (计算机组成原理)第二章数据的表示和运算-第三节2:IEEE754标准
- [WPF疑难]如何禁用WPF窗口的系统菜单(SystemMenu)
- java坐标代码_java实现计算地理坐标之间的距离
- 说一下你对多态的理解?_如何去理解java中的多态?从jvm角度分析也许让你更清晰...
- Swift 个人学习笔记 - 01: A Swift Tour
- win10设置无盘服务器,win10系统无盘安装系统的操作方法
- HTTP:超文本传输协议
- 移远通信亮相CCBN2021,助推视听媒体等领域不断创新
- 解决百度网盘下载慢的方案
- ROSERROR : C++ filt命令
- [Acc]4379. 两个闹钟 暴力
- C++OpenCV系统学习(3)——图像混合、调整亮度与对比度
- WPF发布程序后未授予信任的解决办法
- cad怎样转换成pdf格式?四个步骤完成
- SQL语法之分组函数,分组查询(进阶5)and连接查询(sql92语法进阶6)
- 第八届中国R语言会议(北京)纪要
热门文章
- MySQL中针对SQL语句优化
- 嵌入式开发需掌握的技能有哪些
- git基本命令与git基本命令-远程
- 长安链源码学习--提案(Proposer)(五)
- Mybatis源码解析——入门级
- javaweb登录验证码的实现
- C语言程序设计|文件操作
- linux strcpy函数,C语言中函数strcpy ,strncpy ,strlcpy,strcpy_s的用法
- java02win7x64_Win 7 64位下jdk(java)1.8.X(64位)的经验
- java functionex_Atitit. atiJavaExConverter4js 新的特性