环境:VB,重点是整理思路。
零、序
0.在ExcelHome上遇到很多凑数的贴子,粗略看过香川的代码,用的递归,看不懂,一直觉得这个比较难。春节无事,尝试挑战。
1.研习香川的贴子,花了很长时间,贴子里的解释不多,很费劲,主要是递归绕来绕去就绕晕了,最后发觉根本看不懂,放弃。
2.咨询老同学,点名这东西属于“背包问题”的简化版。
3.网上找了些背包的贴子,绝大多数都只有代码,关于解题思路说的太少,难以理解代码形成的过程。唯一一个有思路的贴子,用的全是数学符号,还是看不懂。
4.心得:看别人的代码比自己写代码还难。
5.不再看别人写的,打算自己硬编。
一、题型
有100张金额不等的发票,期望找到金额为1000元的各张发票的组合。
二、思路
(一)将发票按金额将序排列。
(二)简化问题:只找能够与第一张发票凑成1000的其他发票。
1st.FatherArr=发票集合,包含编号和金额;通过循环,使Arr=小于1000元的发票集合。
2nd.循环Arr,从第一张开始往下加:
    1.如果金额小于1000,说明有希望凑成1000,将发票编号记录到临时变量(如ID),金额合计记录到临时变量(如Sum),然后接着加下一个。
2.如果金额等于1000,达成期望,把ID记录到结果数组(如Answer),搞定!
3.如果金额大于1000,失败,说明最后一次把数加冒了。
由于发票是降序排列,后面没准有可以能够与加冒之前凑成1000的票,但是怎么弄?
      按照以上思路再循环一次!
      只不过这次目标值变成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
四、感慨
中间不断调试,递来递去太乱了。
写完代码,发现竟然和香川的代码结构上差不多,也是醉了,这玩意果然只能自己写。

【思路整理】凑数问题相关推荐

  1. 张铁柱-前端实现《低代码可视化编辑器》(一)思路整理 React-dnd+Ts

    张铁柱-前端实现<低代码可视化编辑器>(一)思路整理 React-dnd+Ts 先上效果: 拖拽生成页面+调整顺序 最近,接到任务做一个低代码编辑器,于是着手整理一下思路,调研一下实现方式 ...

  2. GAN框架研究与思路整理

      本文内容将着重分析当前GAN原理及其应用场景,比对其相对于传统深度学习方法在图像生成等方面的区别 一.原始GAN原理           原始GAN论文中的思想为生成模型与判别模型间的零和博弈,通 ...

  3. VL53L0X 底层思路整理(1)

    传感器资料思路整理 世界上最小的飞行时间测距和姿态探测传感器 特点: •完全集成的微型模块 – 940nm激光VCSEL – VCSEL驱动程序 –带有高级嵌入式测距传感器的微控制器 – 4.4 x ...

  4. C#FFmpeg视频采集与推送RTMP服务器代码思路整理

    C#视频采集与推送RTMP服务器代码思路整理:在看过FFmpeg后是否认为写C#的视频流采集和推送还是一头雾水啊?深有此感.领导是C#的高手,说可以通过C或C++的代码直接复制粘贴到C#工程然后进行适 ...

  5. 多智能体强化学习思路整理

    多智能体强化学习算法思路整理 目录 摘要 背景和意义 研究背景 强化学习 多智能体强化学习与博弈论基础 研究意义 问题与挑战 问题分类 问题分析 环境的不稳定性与可扩展性的平衡 部分可观测的马尔可夫决 ...

  6. 前端实现登录、登出、请求数据的一些思路整理

    前端实现登录.登出.请求数据的一些思路整理(基于React.JWT技术) 登录.登出和数据请求是两种不同的数据交互方式,是互相独立的. 登录.登出基于 JWT(JSON WEB TOKEN) 技术,通 ...

  7. 2018年美国大学生数学建模竞赛原题、翻译及思路整理

    参加了2018年的美赛,整理了一些参考资料,需要的话就拿去吧. 具体内容是:2018年美国大学生数学建模竞赛原题.翻译及思路整理,有兴趣的小伙伴可以看看 链接:https://pan.baidu.co ...

  8. 探索性数据分析的思路整理

    探索性数据分析的思路整理 读取数据 清洗数据,对构建的数据进行整理 探索全局特征, 通过直方图,散点图,聚合函数对数据进行全局的了解 探索数据的分组特征,通过分组操作分析数据集 %matplotlib ...

  9. 华为杯数学建模思路整理

    华为杯数学建模思路整理 1.对于题目: 1.1 题目加上使用的模型进行命名,一定要注意字眼和格式:1.2 目录格式,简洁清爽,表现出使用的模型:1.3 别人的东西,加上文献引用;(**)1.4 对于评 ...

  10. 2021美赛D题艺术家思路整理

    问题整理 使用influence_data数据集或其部分创建音乐影响力的(多个)定向网络,其中影响者与关注者相连.开发捕捉此网络中"音乐影响的参数".通过创建定向影响网络的子网络来 ...

最新文章

  1. ubuntu服务器版编辑文件,Ubuntu 服务器版 18.04.4 固定 IP 设置
  2. c语言规定标识符 字符串,c语言中标识符命名规则是怎样的
  3. 如何知道当前像素的顶点坐标_GT 大神 | 如何高效渲染流体效果(绝对干货)
  4. java我的世界极限生存_我的世界 1.7.10 极限生存整合包
  5. (计算机组成原理)第二章数据的表示和运算-第三节2:IEEE754标准
  6. [WPF疑难]如何禁用WPF窗口的系统菜单(SystemMenu)
  7. java坐标代码_java实现计算地理坐标之间的距离
  8. 说一下你对多态的理解?_如何去理解java中的多态?从jvm角度分析也许让你更清晰...
  9. Swift 个人学习笔记 - 01: A Swift Tour
  10. win10设置无盘服务器,win10系统无盘安装系统的操作方法
  11. HTTP:超文本传输协议
  12. 移远通信亮相CCBN2021,助推视听媒体等领域不断创新
  13. 解决百度网盘下载慢的方案
  14. ROSERROR : C++ filt命令
  15. [Acc]4379. 两个闹钟 暴力
  16. C++OpenCV系统学习(3)——图像混合、调整亮度与对比度
  17. WPF发布程序后未授予信任的解决办法
  18. cad怎样转换成pdf格式?四个步骤完成
  19. SQL语法之分组函数,分组查询(进阶5)and连接查询(sql92语法进阶6)
  20. 第八届中国R语言会议(北京)纪要

热门文章

  1. MySQL中针对SQL语句优化
  2. 嵌入式开发需掌握的技能有哪些
  3. git基本命令与git基本命令-远程
  4. 长安链源码学习--提案(Proposer)(五)
  5. Mybatis源码解析——入门级
  6. javaweb登录验证码的实现
  7. C语言程序设计|文件操作
  8. linux strcpy函数,C语言中函数strcpy ,strncpy ,strlcpy,strcpy_s的用法
  9. java02win7x64_Win 7 64位下jdk(java)1.8.X(64位)的经验
  10. java functionex_Atitit. atiJavaExConverter4js  新的特性