ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 【最优组合算法】之递归以及循环算法,及其组合结果输出实用附件

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2014-10-21 15:43 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 香川群子 于 2014-10-22 16:08 编辑

组合算法很多,其中递归算法因为结构简单,容易写成通用的代码,很具有实用性。

但需要注意的是:递归的方法,速度效率肯定远远不如数组运算。
因此,虽然附件没有作限制,但仍不建议进行巨量组合的运算。


附件的特点,首先不用说,都是递归算法的代码。
其次、输出特点如下:

一、分3种输出方式:
① c=0 时,在同文件夹下生成 CombinResult.txt 的文本文件。组合数量大时效果好。

② c=1 时,合并组合结果为由指定分隔符w分隔的字符串后单列输出。

③ c=n 时,组合结果分为n列输出、各个输出区域之间空一列。


二、工作表输出时,可以按限制指定行数r进行多列(c=1时)、或多区域(c=n时)输出。

三、c=0 或 c=1 时可选择分隔符w(任意长度字符),如留空则组合结果无分隔。

…………具体下载附件试一试便知。

组合之递归算法.zip (15.54 KB, 下载次数: 523)



增加附件,加入了数组循环算法。
数组循环算法,速度可以提高很多倍。
但组合解数很多很多时,程序总耗时仅仅取决于输出组合内容的多少,
而此时,组合计算的耗时则完全可以忽略不计……


递归及循环的组合算法.zip (26.85 KB, 下载次数: 452)

再增加一个有趣的数组位置移动组合算法。
虽然速度效率没有Do循环的高,但算法逻辑清晰,值得学习。
但是没有把输出部分做完整,只做了最简单的输出小于工作表行数部分。

数组位置移动组合算法.zip (9.73 KB, 下载次数: 379)











评分

4

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-21 16:08 | 显示全部楼层
本帖最后由 香川群子 于 2014-10-21 16:19 编辑

文本输出的递归过程主要代码如下:

Sub dgZH0(s$, i&, t&) 'by kagawa
    For j = i + 1 To m - n + t
        If t = n Then
            k = k + 1: Print #1, Mid(s & w & sj(j, 1), Len(w) + 1)
        Else
            Call dgZH0(s & w & sj(j, 1), j, t + 1)
        End If
    Next
End Sub

结构非常简单。
…………


工作表单列输出的递归过程主要代码如下:(含多列输出)
Sub dgZH1(s$, i&, t&) 'by kagawa
    For j = i + 1 To m - n + t
        If t = n Then
            k = k + 1: jg(k, 1) = Mid(s & w & sj(j, 1), Len(w) + 1)
            If k = r Then [iv1].End(1).Offset(, 1).Resize(r) = jg: k = 0 '增加了多列输出部分
        Else
            Call dgZH1(s & w & sj(j, 1), j, t + 1)
        End If
    Next
End Sub


结构也还是简单的…………


工作表多列输出的递归过程主要代码如下:(也含多列输出)
Sub dgZH2(a&(), i&, t&) 'by kagawa
    For j = i + 1 To m - n + t
        a(t) = j
        If t = n Then
            k = k + 1
            For l = 1 To n '里面多了一层多列展开赋值的循环代码
                jg(k, l) = sj(a(l), 1)
            Next
            If k = r Then [iv1].End(1).Offset(, 2).Resize(r, n) = jg: k = 0 '这部分也是多列输出
        Else
            Call dgZH2(a, j, t + 1)
        End If
    Next
End Sub

多了一个记录组合状态的数组,以及多列赋值的内层循环。
其它部分也还是差不多的。

点评

香川美女,这是目前为止最快的算法,一边释放内存,一边输出结果,不会全部输出结果再释放内存(会死机)。暂时没有人可以超越!我的神,好像不能忽略空值。  发表于 2015-3-29 17:20
蓝色语句代表的多列输出,又是一大创新……工作表的行乘以列这块地方还是够大的,要溢出的话,估计计算机会受不了的……  发表于 2014-10-21 18:42
“by kagawa”是本论坛重要的一个品牌!  发表于 2014-10-21 18:36

TA的精华主题

TA的得分主题

发表于 2014-10-21 17:15 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-10-21 17:32 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-10-21 17:32 | 显示全部楼层
麻烦告之。急于求算法。优化组合。

TA的精华主题

TA的得分主题

发表于 2014-10-21 18:42 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
值得学习,收藏!!!毫无疑问地顶帖!!!

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-10-21 19:00 | 显示全部楼层
我靠,我看了短命10年都值了。

TA的精华主题

TA的得分主题

发表于 2014-10-21 19:05 | 显示全部楼层
本帖最后由 张雄友 于 2014-10-21 19:15 编辑

香川群子,灰袍法师, 小fisher,百度不到去谷歌,aoe1981 真是这方面的人才啊!!!

点评

香川和灰袍是真正研究算法的 我是拿来主义 我只是对他们算法二次加工包装 使得用户接口更方便一点  发表于 2014-10-22 10:18
我晕……【小fisher】我一次都没听说过……  发表于 2014-10-21 20:41

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-10-21 19:12 | 显示全部楼层
虽然不懂,但还是觉得很厉害。

点评

这就是现代成语“不明觉厉”的意思吧……  发表于 2014-10-21 19:24

TA的精华主题

TA的得分主题

发表于 2014-10-21 19:17 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
真的很有用,顶!
  1. Dim sj, jg(), m&, n&, k&, r&, c&, w$, cnt&
  2. Sub Combin_dg() 'by kagawa
  3.     tms = Timer
  4.     m = [a1].End(4).Row: sj = [a1].Resize(m): [a:a].EntireColumn.AutoFit
  5.     n = [b2]: k = WorksheetFunction.Combin(m, n)
  6.     w = [b4]
  7.     r = [b5]: If r = 0 Then r = 50000: [b5] = r
  8.     c = Val([b6]): If c Then cnt = ((k - 1) \ r + 1) * IIf(c = 1, 1, n + 1) + 6: If cnt > Columns.Count Then MsgBox cnt & " > " & Columns.Count & " Err !": Exit Sub
  9.     [e1].Resize(, Columns.Count - 5) = 1: [e1].CurrentRegion = "": [e1] = "Output": [b9:b12] = "":
  10.    
  11.     k = 0: cnt = 0: tm1 = Timer
  12.     If c = 0 Then
  13.         Open ActiveWorkbook.Path & "\CombinResult.txt" For Output As #1
  14.         Call dgZH0("", 0, 1)
  15.         Close #1
  16.     ElseIf c = 1 Then
  17.         ReDim jg(1 To r, 1 To 1)
  18.         Call dgZH1("", 0, 1)
  19.         If [b3] > r Then [iv1].End(1).Offset(, 1).Resize(k) = jg
  20.         [f1].Resize(, [b7]).EntireColumn.AutoFit
  21.     Else '
  22.         c = n: [b6] = n
  23.         [f1].Resize(, 1 + [b7]).ColumnWidth = [a1].ColumnWidth
  24.         ReDim a&(1 To n): ReDim jg(1 To r, 1 To n)
  25.         Call dgZH2(a, 0, 1)
  26.         If [b3] > r Then [iv1].End(1).Offset(, 2).Resize(k, n) = jg
  27.     End If
  28.    
  29.     [d1] = "":  [b9] = cnt
  30.     If c And [b3] < r Then
  31.         [b10] = Format(Timer - tm1, "0.000"): tm2 = Timer
  32.         [f1].Resize(k, c) = jg: [f1].Resize(, c).EntireColumn.AutoFit: [b11] = Format(Timer - tm2, "0.000")
  33.     End If
  34.     [b12] = Format(Timer - tms, "0.000")
  35.     MsgBox Format(Timer - tms, "0.000s ") & Format([b3], "#,##0") & "/" & Format(cnt, "#,##0")
  36. End Sub
  37. Sub dgZH0(s$, i&, t&) 'by kagawa
  38.     Dim j&
  39.     cnt = cnt + 1
  40.     For j = i + 1 To m - n + t
  41.         If t = n Then k = k + 1: Print #1, Mid(s & w & sj(j, 1), Len(w) + 1) Else Call dgZH0(s & w & sj(j, 1), j, t + 1)
  42.     Next
  43. End Sub
  44. Sub dgZH1(s$, i&, t&) 'by kagawa
  45.     Dim j&
  46.     cnt = cnt + 1
  47.     For j = i + 1 To m - n + t
  48.         If t = n Then
  49.             k = k + 1: jg(k, 1) = Mid(s & w & sj(j, 1), Len(w) + 1)
  50.             If k = r Then [iv1].End(1).Offset(, 1).Resize(r) = jg: k = 0
  51.         Else
  52.             Call dgZH1(s & w & sj(j, 1), j, t + 1)
  53.         End If
  54.     Next
  55. End Sub
  56. Sub dgZH2(a&(), i&, t&) 'by kagawa
  57.     Dim j&, l&
  58.     cnt = cnt + 1
  59.    
  60.     For j = i + 1 To m - n + t
  61.         a(t) = j
  62.         If t = n Then
  63.             k = k + 1
  64.             For l = 1 To n
  65.                 jg(k, l) = sj(a(l), 1)
  66.             Next
  67.             If k = r Then [iv1].End(1).Offset(, 2).Resize(r, n) = jg: k = 0
  68.         Else
  69.             Call dgZH2(a, j, t + 1)
  70.         End If
  71.     Next
  72. End Sub
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-7-1 17:03 , Processed in 0.044272 second(s), 20 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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