ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: aoe1981

[原创] 邯郸学步:再做递归凑数之列出开票明细

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-23 23:06 | 显示全部楼层
本帖已被收录到知识树中,索引项:递归
哦,忽然明白了,参考循环次数的公式我搞错了:
  1. =SUMPRODUCT(ROUNDUP(($B$2-SUM(INDIRECT("E9:E"&8+$B$3)))/INDIRECT("E9:E"&8+$B$3),),INDIRECT("E9:E"&8+$B$3)^0)
复制代码
上面的公式是求和了,没有求连续的积……
差之毫厘,谬之千里啊……

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-23 23:11 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 aoe1981 于 2014-10-23 23:14 编辑

11楼错误公式已修改:
  1. =PRODUCT(ROUNDUP(($B$2-SUM(INDIRECT("E9:E"&8+$B$3)))/INDIRECT("E9:E"&8+$B$3),))
复制代码
三键结束。
原来,上面的对比数据,我的代码的循环次数为:1.46337E+39        
啧啧,怪不得会等到花儿都谢了……
(1楼附件再次更新,增加了使用建议:循环次数大于10000000次,就建议“误差匹配”,否则可尝试“精确匹配”)

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-23 23:18 | 显示全部楼层
  下面是我研制这个附件的过程,这个过程中的中间结果还是很愚蠢的,但是很有意义,因为:
  “中间结果或中间步骤最能反映思路”!!!
  因此,自我做一个标记:
  这就是,我一开始是用嵌套for循环4层固定解决只选择4种商品时的金额匹配问题的,以检验我的解决问题的思路是否正确、有效,在此基础上,在利用递归,抽象出共同步骤,扩展至任意n层循环的一揽子解决……
  这些中间代码如下:
  
  1. '以下为开票明细(aoe1981之小学版)过渡代码:
  2. '(普通4层循环代码,并由此步入递归)
  3. Option Explicit
  4. Public Sub CouShu0()
  5. Dim n%, zje#, dj, i&, wc As Boolean, wcz#, t#
  6. t = Timer
  7. n = Range("b3").Value '项目数
  8. If n = 0 Then MsgBox "请勾选项目!", , "友情提示": Exit Sub
  9. zje = Range("b2").Value '总金额
  10. ReDim sl&(1 To n, 1 To 1), je#(1 To n) '数量、金额
  11. dj = Range("e9:e" & 8 + n).Value '单价
  12. If Range("b4").Value <> "是" Then wc = False Else wc = True: wcz = Range("b5").Value
  13. je(1) = zje - WorksheetFunction.Sum(dj)
  14. sl(1, 1) = je(1) \ dj(1, 1)
  15. Dim i1&, i2&, i3&, i4&, pd As Boolean, s$, gd
  16. For i1 = sl(1, 1) To 0 Step -1
  17.     je(2) = je(1) - dj(1, 1) * i1: sl(2, 1) = je(2) \ dj(2, 1)
  18.     For i2 = sl(2, 1) To 0 Step -1
  19.         je(3) = je(2) - dj(2, 1) * i2: sl(3, 1) = je(3) \ dj(3, 1)
  20.         For i3 = sl(3, 1) To 0 Step -1
  21.             je(4) = je(3) - dj(3, 1) * i3: sl(4, 1) = je(4) \ dj(4, 1)
  22.             For i4 = sl(4, 1) To 0 Step -1
  23.                 If wc Then
  24.                     If Abs(je(4) - dj(4, 1) * i4) <= wcz Then pd = True: s = i1 & "-" & i2 & "-" & i3 & "-" & i4: GoTo 100
  25.                 ElseIf je(4) - dj(4, 1) * i4 = 0 Then
  26.                     pd = True
  27.                     s = i1 & "-" & i2 & "-" & i3 & "-" & i4
  28.                     GoTo 100
  29.                 End If
  30.             Next i4
  31.         Next i3
  32.     Next i2
  33. Next i1
  34. 100:
  35. gd = Split(s, "-")
  36. If pd Then
  37.     For i = 1 To n
  38.         sl(i, 1) = gd(i - 1) + 1
  39.     Next i
  40.     Range("f9").Resize(n) = sl
  41.     MsgBox "用时:" & Format(Timer - t, "0.0000") & "秒。", , "友情提示"
  42. Else
  43.     MsgBox "抱歉,没有找到!", , "友情提示"
  44. End If
  45. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-23 23:32 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
  经过多次测试,发现一些特点以及问题:
  1.在精确匹配下,商品单价的选择尽量不要出现小数;
  2.商品单价的选择,最好有高有低,体现出较大的离散程度;
  3.可能在满足上述条件的情况下,虽然预计循环次数可能依然很大,但是也是可以迅速得到精确匹配结果的,如下图:
   360截图-19356494.jpg
  希望得到解决的问题:
  1.万一在精确匹配时一时半会不成功,等候不住的时候,最好不要老是强行关闭,“结束任务”,最好是可以根据已运行时间进行强行退出!
  其他……目前未知的……

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-23 23:35 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
  下图可以看出:整数结果下精确匹配的优势!
   360截图-19799740.jpg

TA的精华主题

TA的得分主题

发表于 2014-10-24 08:25 | 显示全部楼层
精确匹配 改为 模糊匹配,只需要改为:目标值+误差范围 就可以了。
我认为没啥难度。

由于原帖的要求,必须是精确匹配,所以我不认为有改成模糊匹配的需要。

…………
至于某些组合无匹配组合,或需要计算很长时间,
可以根据实际情况,设置中途退出条件、如递归计算次数达到某个数值时退出即可。



评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-10-24 08:27 | 显示全部楼层
我在《2014新年元旦第一强帖:实用凑数凑金额高效递归剪枝算法》帖子中,
就有递归计算深度的设置。可以防止巨量计算造成的假死机出现……但显然计算对象较多时会漏过很多组合的计算。

点评

向您学习,似乎道路很远很远……继续努力中……  发表于 2014-10-24 08:37

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-28 14:20 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
以下为递归调用1000万次没有找到精确匹配结果时强行退出的代码,大约用时40秒:
  1. Sub DG(k%)
  2. Dim j&, i&
  3. If pd Then Exit Sub '找到匹配结果时直接逐层返回
  4. cnt = cnt + 1
  5. If cnt > 10000000 Then MsgBox "程序运行超时(" & Format(Timer - t, "0.0000") & "秒),即将强行结束,建议启用误差匹配!", , "友情提示": End
  6. If k = n Then
  7.     For j = sl(k, 1) To 0 Step -1
  8.         If wc Then
  9.             If Abs(je(k) - dj(k, 1) * j) <= wcz Then '误差匹配
  10.                 pd = True
  11.                 ss(k) = j
  12.                 For i = 1 To n
  13.                     s = s & "-" & ss(i)
  14.                 Next i
  15.             End If
  16.         Else
  17.             If je(k) - dj(k, 1) * j = 0 Then '精确匹配
  18.                 pd = True
  19.                 ss(k) = j
  20.                 For i = 1 To n
  21.                     s = s & "-" & ss(i)
  22.                 Next i
  23.             End If
  24.         End If
  25.     Next j
  26. Else
  27.     For j = sl(k, 1) To 0 Step -1
  28.         je(k + 1) = je(k) - dj(k, 1) * j '下层金额=本层金额-本层单价*本层数量
  29.         sl(k + 1, 1) = je(k + 1) \ dj(k + 1, 1) '下层数量=下层金额\下层单价
  30.         ss(k) = j
  31.         DG k + 1
  32.     Next j
  33. End If
  34. End Sub
复制代码
1楼附件已更新。

TA的精华主题

TA的得分主题

发表于 2015-8-31 16:23 | 显示全部楼层
版主,求助??{:soso_e183:}
题目:现有7根长度为1200mm的木材,需要切出相应所需长度规格,但在切断过程序中有些损耗,有效的切削长度控制在1195mm~1199mm。
求解如何才能切断出如下所需规格数量?
长度mm        数量
310                   6
143                 2
367                  2
97               11
206               16
208                2
181            4

TA的精华主题

TA的得分主题

发表于 2015-8-31 16:57 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
ly129001 发表于 2015-8-31 16:23
版主,求助??
题目:现有7根长度为1200mm的木材,需要切出相应所需长度规格,但在切断过程 ...

Plan.png
很简单。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-25 00:59 , Processed in 0.045677 second(s), 14 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表