ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 史上最酷的Excel VBA 组合算法 代码

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2013-8-19 14:32 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:其他结构和算法
{:soso_e196:}膜拜膜拜

TA的精华主题

TA的得分主题

发表于 2013-8-19 14:40 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-8-20 14:35 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
{:soso_e182:}

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-20 14:54 | 显示全部楼层
lin505 发表于 2013-8-19 14:40
http://club.excelhome.net/thread-1047617-1-1.html
大师能不能帮我这个排一下?

这个用递归剪枝法计算,比循环计算全部组合的算法,效率高的多。


已在你的原帖中给予解答。

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-23 16:39 | 显示全部楼层
顺便把排列算法也做了些改进……但尚未全部完成。

Permut1.zip

24.59 KB, 下载次数: 98

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-24 18:25 | 显示全部楼层
这个已经是目前最快的排列代码了:
  1. Sub GetPermut_Mid1()
  2.     Dim i&, j&, k&, l&, m&, n&, s$
  3.     m = [a1].End(4).Row: sj = [a1].Resize(m): n = [b1]
  4.    
  5.     tms = Timer
  6.    
  7.     k = Application.Permut(m, n)
  8.     ReDim jg1$(1 To k, 1 To 1)
  9.    
  10.     For j = 1 To m
  11.         If Len(sj(j, 1)) > l Then l = Len(sj(j, 1))
  12.     Next
  13.     ReDim sj1$(1 To m)
  14.     s = String(l, " ")
  15.     For j = 1 To m
  16.         sj1(j) = Right(s & sj(j, 1), l)
  17.     Next
  18.    
  19.     ReDim a&(n)
  20.     ReDim b&(1 To m)
  21.     s = ""
  22.     For j = 1 To n - 1
  23.         a(j) = j
  24.         b(j) = 1
  25.         s = s & sj1(j)
  26.     Next
  27.     s = s & sj1(j)
  28.     i = n - 1: r = m - i: k = 0 ':j = n
  29.    
  30.     Do
  31.         Do
  32.             i = i + 1
  33.             If b(i) = 0 Then a(j) = i: b(i) = 1: r = r - 1: Exit Do
  34.         Loop
  35.         Mid(s, (j - 1) * l + 1, l) = sj1(i)
  36.         
  37.         If j = n Then
  38.             k = k + 1: jg1(k, 1) = s
  39.             
  40.             If r = 0 Then
  41.                 Do
  42.                     j = j - 1
  43.                     If a(j) < m Then
  44.                         ReDim b&(1 To m)
  45.                         s = String(l * n, " ")
  46.                         For j = 1 To j - 1
  47.                             b(a(j)) = 1
  48.                             Mid(s, (j - 1) * l + 1, l) = sj1(a(j))
  49.                         Next
  50.                         
  51.                         i = a(j)
  52.                         Do While i < m
  53.                             i = i + 1
  54.                             If b(i) = 0 Then
  55.                                 a(j) = i: b(i) = 1
  56.                                 Mid(s, (j - 1) * l + 1, l) = sj1(i)
  57.                                 i = 0: r = m - j: j = j + 1
  58.                                 Exit Do
  59.                             End If
  60.                         Loop
  61.                         If i = 0 Then Exit Do
  62.                     End If
  63.                 Loop Until j = 1
  64.                 If j = 1 Then Exit Do
  65.             End If
  66.         Else
  67.             j = j + 1
  68.             i = 0
  69.         End If
  70.     Loop

  71.     [b11] = Format(Timer - tms, "0.000s PermutDo1 ") & k
  72.    
  73.     If [c1] = "" And k < 65536 Then
  74.         tms = Timer: [d:d] = "": [d1].Resize(k) = jg1: [d1].EntireColumn.AutoFit
  75.         [b11] = [b11] & " " & Format(Timer - tms, "0.000s")
  76.     End If
  77.     Erase jg1
  78. End Sub
复制代码

Permut2.rar

18.6 KB, 下载次数: 170

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-24 18:26 | 显示全部楼层
比组合复杂多了……

刚刚写完,或许还可以再做些优化、改进。
  1. Function PermutDo(m&, n&)
  2.     Dim i&, j&, k&, l&
  3.     tms = Timer
  4.    
  5.     ReDim a&(n)
  6.     ReDim b&(1 To m)
  7.     For j = 1 To n - 1
  8.         a(j) = j
  9.         b(j) = 1
  10.     Next
  11.     i = n - 1: r = m - i: k = 0 ':j = n
  12.    
  13.     Do
  14.         Do
  15.             i = i + 1
  16.             If b(i) = 0 Then a(j) = i: b(i) = 1: r = r - 1: Exit Do
  17.         Loop
  18.         
  19.         If j = n Then
  20.             k = k + 1
  21.             If r = 0 Then
  22.                 Do
  23.                     j = j - 1
  24.                     If a(j) < m Then
  25.                         ReDim b&(1 To m)
  26.                         For j = 1 To j - 1
  27.                             b(a(j)) = 1
  28.                         Next
  29.                         
  30.                         i = a(j)
  31.                         Do While i < m
  32.                             i = i + 1
  33.                             If b(i) = 0 Then
  34.                                 a(j) = i: b(i) = 1
  35.                                 i = 0: r = m - j: j = j + 1
  36.                                 Exit Do
  37.                             End If
  38.                         Loop
  39.                         If i = 0 Then Exit Do
  40.                     End If
  41.                 Loop Until j = 1
  42.                 If j = 1 Then Exit Do
  43.             End If
  44.         Else
  45.             j = j + 1
  46.             i = 0
  47.         End If
  48.     Loop
  49.     PermutDo = Format(Timer - tms, "0.0000s ") & " kagawa Do2 Permut(" & m & "," & n & ")= " & k
  50.    
  51. End Function
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-25 10:50 | 显示全部楼层
优化完成,速度又提高了一倍。

下面是速度函数
  1. Function PermutDo(ByVal m&, ByVal n&)
  2.     Dim i&, j&, k&
  3.     tms = Timer
  4.    
  5.     n = n - 1: ReDim a&(n)
  6.     ReDim b(1 To m) As Boolean
  7.     For j = 0 To n - 1
  8.         a(j) = 1 + j
  9.         b(1 + j) = True
  10.     Next
  11.    
  12.     'i = 0: j = n: k = 0
  13.     Do
  14.         If j = n Then
  15.             For i = 1 To m
  16.                 If Not b(i) Then
  17.                     a(j) = i
  18.                     k = k + 1
  19.                 End If
  20.             Next
  21.             If n = 0 Then Exit Do
  22.             Do
  23.                 j = j - 1
  24.                 i = a(j): b(i) = False
  25.                 For i = i + 1 To m
  26.                     If Not b(i) Then
  27.                         a(j) = i: b(i) = True
  28.                         i = 0: Exit Do
  29.                     End If
  30.                 Next
  31.             Loop Until j = 0
  32.             If i Then Exit Do
  33.         Else
  34.             j = j + 1
  35.             If j < n Then
  36.                 For i = 1 To m
  37.                     If Not b(i) Then
  38.                         a(j) = i: b(i) = True
  39.                         Exit For
  40.                     End If
  41.                 Next
  42.             End If
  43.         End If
  44.     Loop
  45.     PermutDo = Format(Timer - tms, "0.0000s ") & " kagawa Do Permut(" & m & "," & n + 1 & ")= " & k
  46.    
  47. End Function
复制代码
下面是可输出排列结果的代码
  1. Sub GetPermut_Mid()
  2.     Dim i&, j&, k&, l&, m&, n&, s$
  3.     tms = Timer
  4.    
  5.     m = [a1].End(4).Row: sj = [a1].Resize(m): n = [b1]
  6.     k = Application.Permut(m, n)
  7.     ReDim jg1$(1 To k, 1 To 1): k = 0
  8.    
  9.     For j = 1 To m
  10.         If Len(sj(j, 1)) > l Then l = Len(sj(j, 1))
  11.     Next
  12.     ReDim sj1$(1 To m)
  13.     s = String(l, " ")
  14.     For j = 1 To m
  15.         sj1(j) = Right(s & sj(j, 1), l)
  16.     Next
  17.    
  18.     n = n - 1: ReDim a&(n)
  19.     ReDim b(1 To m) As Boolean
  20.     s = String(l * n + l, " ")
  21.     For j = 0 To n - 1
  22.         a(j) = 1 + j
  23.         b(1 + j) = True
  24.         Mid(s, j * l + 1, l) = sj1(1 + j)
  25.     Next
  26.    
  27.     'i = 0: j = n: k = 0
  28.     Do
  29.         If j = n Then
  30.             For i = 1 To m
  31.                 If Not b(i) Then
  32.                     a(j) = i
  33.                     Mid(s, j * l + 1, l) = sj1(i)
  34.                     k = k + 1
  35.                     jg1(k, 1) = s
  36.                 End If
  37.             Next
  38.             If n = 0 Then Exit Do
  39. '            If s = "6543" Then Stop
  40.             Do
  41.                 j = j - 1
  42.                 i = a(j): b(i) = False
  43.                 For i = i + 1 To m
  44.                     If Not b(i) Then
  45.                         a(j) = i: b(i) = True
  46.                         Mid(s, j * l + 1, l) = sj1(i)
  47.                         i = 0
  48.                         Exit Do
  49.                     End If
  50.                 Next
  51.             Loop Until j = 0
  52.             If i Then Exit Do
  53.         Else
  54.             j = j + 1
  55.             If j < n Then
  56.                 For i = 1 To m
  57.                     If Not b(i) Then
  58.                         a(j) = i: b(i) = True
  59.                         Mid(s, j * l + 1, l) = sj1(i)
  60.                         Exit For
  61.                     End If
  62.                 Next
  63.             End If
  64.         End If
  65.     Loop

  66.     [b14] = Format(Timer - tms, "0.000s PermutDo ") & k
  67.    
  68.     If [c1] = "" And k < 65536 Then
  69.         tms = Timer: [h:h] = "": [h1].Resize(k) = jg1: [h1].EntireColumn.AutoFit
  70.         [b14] = [b14] & " " & Format(Timer - tms, "0.000s")
  71.     End If
  72.     Erase jg1
  73. End Sub
复制代码

Permut2.rar

21.02 KB, 下载次数: 135

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-25 14:07 | 显示全部楼层
本帖最后由 香川群子 于 2013-8-25 14:34 编辑

继续改进:

  1. Sub GetPermut_Mid6()
  2.     Dim i&, ii&, j&, k&, l&, m&, n&, s$
  3.     tms = Timer
  4.    
  5.     m = [a1].End(4).Row: sj = [a1].Resize(m): n = [b1]
  6.     k = Application.Permut(m, n)
  7.     ReDim jg1$(1 To k, 1 To 1): k = 0
  8.    
  9.     For j = 1 To m
  10.         If Len(sj(j, 1)) > l Then l = Len(sj(j, 1))
  11.     Next
  12.     ReDim sj1$(1 To m)
  13.     s = String(l, " ")
  14.     For j = 1 To m
  15.         sj1(j) = Right(s & sj(j, 1), l)
  16.     Next
  17.    
  18.     n = n - 1: ReDim a&(n)
  19.     ReDim b(1 To m) As Boolean
  20.     s = String(l * n + l, " ")
  21.     For j = 0 To n - 1
  22.         a(j) = 1 + j
  23.         b(1 + j) = True
  24.         Mid(s, j * l + 1, l) = sj1(1 + j)
  25.     Next
  26.    
  27.     'i = 0: j = n: k = 0
  28.     Do
  29.         For i = 1 To m
  30.             If Not b(i) Then
  31. '                a(j) = i
  32.                 Mid(s, j * l + 1, l) = sj1(i)
  33.                 k = k + 1
  34.                 jg1(k, 1) = s
  35.             End If
  36.         Next
  37.         If n = 0 Then Exit Do
  38. '        If s = "6543" Then Stop
  39.         Do
  40.             j = j - 1: i = a(j): b(i) = False
  41.             For i = i + 1 To m
  42.                 If Not b(i) Then
  43.                     a(j) = i: b(i) = True
  44.                     Mid(s, j * l + 1, l) = sj1(i)
  45.                     If j < n - 1 Then
  46.                         i = 0
  47.                         Do
  48.                             i = i + 1
  49.                             If Not b(i) Then
  50.                                 j = j + 1: a(j) = i: b(i) = True
  51.                                 Mid(s, j * l + 1, l) = sj1(i)
  52.                                 If j = n - 1 Then Exit Do
  53.                             End If
  54.                         Loop
  55.                     End If
  56.                     j = n: Exit Do
  57.                 End If
  58.             Next
  59.         Loop Until j = 0
  60.         If j = 0 Then Exit Do
  61.     Loop
  62.     [b16] = Format(Timer - tms, "0.000s PermutDo6 ") & k
  63.    
  64.     If [c1] = "" And k < 65536 Then
  65.         tms = Timer: [j:j] = "": [j1].Resize(k) = jg1: [j1].EntireColumn.AutoFit
  66.         [b16] = [b16] & " " & Format(Timer - tms, "0.000s")
  67.     End If
  68.     Erase jg1
  69. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-27 21:19 | 显示全部楼层
  1. Function PermutDo6(ByVal m&, ByVal n&)
  2.     Dim i&, j&, k&
  3.     tms = Timer
  4.    
  5.     n = n - 1: ReDim a&(n)
  6.     ReDim b(1 To m) As Boolean
  7.     For j = 0 To n - 1
  8.         a(j) = 1 + j
  9.         b(1 + j) = True
  10.     Next
  11.    
  12.     'i = 0: j = n: k = 0
  13.     Do
  14.         For i = 1 To m
  15.             If Not b(i) Then
  16. '                a(j) = i
  17.                 k = k + 1
  18.             End If
  19.         Next
  20.         
  21.         Do Until j = 0
  22.             j = j - 1: i = a(j): b(i) = False
  23.             For i = i + 1 To m
  24.                 If Not b(i) Then
  25.                     a(j) = i: b(i) = True
  26.                     If j < n - 1 Then
  27.                         i = 0
  28.                         Do
  29.                             i = i + 1
  30.                             If Not b(i) Then
  31.                                 j = j + 1: a(j) = i: b(i) = True
  32.                                 If j = n - 1 Then Exit Do
  33.                             End If
  34.                         Loop
  35.                     End If
  36.                     j = n: Exit Do
  37.                 End If
  38.             Next
  39.         Loop
  40.     Loop Until j = 0
  41.     PermutDo6 = Format(Timer - tms, "0.0000s ") & " kagawa Do6 Permut(" & m & "," & n + 1 & ")= " & k
  42.    
  43. End Function
  44. Function PermutDo5(ByVal m&, ByVal n&)
  45.     Dim i&, j&, k&
  46.     tms = Timer
  47.    
  48.     n = n - 1: ReDim a&(n)
  49.     ReDim b(1 To m) As Boolean
  50.     For j = 0 To n - 1
  51.         a(j) = 1 + j
  52.         b(1 + j) = True
  53.     Next
  54.    
  55.     'i = 0: j = n: k = 0
  56.     Do
  57.         For i = 1 To m
  58.             If Not b(i) Then
  59. '                a(j) = i
  60.                 k = k + 1
  61.             End If
  62.         Next
  63.         
  64.         Do Until j = 0
  65.             j = j - 1: i = a(j): b(i) = False
  66.             For i = i + 1 To m
  67.                 If Not b(i) Then
  68.                     a(j) = i: b(i) = True
  69.                     i = 0: Exit Do
  70.                 End If
  71.             Next
  72.         Loop
  73.         If i Then Exit Do
  74.         
  75.         For j = j + 1 To n - 1
  76.             For i = i + 1 To m
  77.                 If Not b(i) Then
  78.                     a(j) = i: b(i) = True
  79.                     Exit For
  80.                 End If
  81.             Next
  82.         Next
  83.     Loop
  84.     PermutDo5 = Format(Timer - tms, "0.0000s ") & " kagawa Do5 Permut(" & m & "," & n + 1 & ")= " & k
  85.    
  86. End Function
复制代码
  1. Sub GetPermut_Mid6()
  2.     Dim i&, ii&, j&, k&, l&, m&, n&, s$
  3.     tms = Timer
  4.    
  5.     m = [a1].End(4).Row: sj = [a1].Resize(m): n = [b1]
  6.     k = Application.Permut(m, n)
  7.     ReDim jg1$(1 To k, 1 To 1): k = 0
  8.    
  9.     For j = 1 To m
  10.         If Len(sj(j, 1)) > l Then l = Len(sj(j, 1))
  11.     Next
  12.     ReDim sj1$(1 To m)
  13.     s = String(l, " ")
  14.     For j = 1 To m
  15.         sj1(j) = Right(s & sj(j, 1), l)
  16.     Next
  17.    
  18.     n = n - 1: ReDim a&(n)
  19.     ReDim b(1 To m) As Boolean
  20.     s = String(l * n + l, " ")
  21.     For j = 0 To n - 1
  22.         a(j) = 1 + j
  23.         b(1 + j) = True
  24.         Mid(s, j * l + 1, l) = sj1(1 + j)
  25.     Next
  26.    
  27.     'i = 0: j = n: k = 0
  28.     Do
  29.         For i = 1 To m
  30.             If Not b(i) Then
  31. '                a(j) = i
  32.                 Mid(s, j * l + 1, l) = sj1(i)
  33.                 k = k + 1
  34.                 jg1(k, 1) = s
  35.             End If
  36.         Next
  37.         If s = "6543" Then Stop
  38.         Do Until j = 0
  39.             j = j - 1: i = a(j): b(i) = False
  40.             For i = i + 1 To m
  41.                 If Not b(i) Then
  42.                     a(j) = i: b(i) = True
  43.                     Mid(s, j * l + 1, l) = sj1(i)
  44.                     If j < n - 1 Then
  45.                         i = 0
  46.                         Do
  47.                             i = i + 1
  48.                             If Not b(i) Then
  49.                                 j = j + 1: a(j) = i: b(i) = True
  50.                                 Mid(s, j * l + 1, l) = sj1(i)
  51.                                 If j = n - 1 Then Exit Do
  52.                             End If
  53.                         Loop
  54.                     End If
  55.                     j = n: Exit Do
  56.                 End If
  57.             Next
  58.         Loop
  59.     Loop Until j = 0

  60.     [b16] = Format(Timer - tms, "0.000s PermutDo6 ") & k
  61.    
  62.     If [c1] = "" And k < 65536 Then
  63.         tms = Timer: [j:j] = "": [j1].Resize(k) = jg1: [j1].EntireColumn.AutoFit
  64.         [b16] = [b16] & " " & Format(Timer - tms, "0.000s")
  65.     End If
  66.     Erase jg1
  67. End Sub

  68. Sub GetPermut_Mid5()
  69.     Dim i&, ii&, j&, k&, l&, m&, n&, s$
  70.     tms = Timer
  71.    
  72.     m = [a1].End(4).Row: sj = [a1].Resize(m): n = [b1]
  73.     k = Application.Permut(m, n)
  74.     ReDim jg1$(1 To k, 1 To 1): k = 0
  75.    
  76.     For j = 1 To m
  77.         If Len(sj(j, 1)) > l Then l = Len(sj(j, 1))
  78.     Next
  79.     ReDim sj1$(1 To m)
  80.     s = String(l, " ")
  81.     For j = 1 To m
  82.         sj1(j) = Right(s & sj(j, 1), l)
  83.     Next
  84.    
  85.     n = n - 1: ReDim a&(n)
  86.     ReDim b(1 To m) As Boolean
  87.     s = String(l * n + l, " ")
  88.     For j = 0 To n - 1
  89.         a(j) = 1 + j
  90.         b(1 + j) = True
  91.         Mid(s, j * l + 1, l) = sj1(1 + j)
  92.     Next
  93.    
  94.     'i = 0: j = n: k = 0
  95.     Do
  96.         For i = 1 To m
  97.             If Not b(i) Then
  98. '                a(j) = i
  99.                 Mid(s, j * l + 1, l) = sj1(i)
  100.                 k = k + 1
  101.                 jg1(k, 1) = s
  102.             End If
  103.         Next
  104. '        If s = "6543" Then Stop
  105.         
  106.         Do Until j = 0
  107.             j = j - 1: i = a(j): b(i) = False
  108.             For i = i + 1 To m
  109.                 If Not b(i) Then
  110.                     a(j) = i: b(i) = True
  111.                     Mid(s, j * l + 1, l) = sj1(i)
  112.                     i = 0: Exit Do
  113.                 End If
  114.             Next
  115.         Loop
  116.         If i Then Exit Do
  117.         
  118.         For j = j + 1 To n - 1
  119.             For i = i + 1 To m
  120.                 If Not b(i) Then
  121.                     a(j) = i: b(i) = True
  122.                     Mid(s, j * l + 1, l) = sj1(i)
  123.                     Exit For
  124.                 End If
  125.             Next
  126.         Next
  127.     Loop

  128.     [b15] = Format(Timer - tms, "0.000s PermutDo5 ") & k
  129.    
  130.     If [c1] = "" And k < 65536 Then
  131.         tms = Timer: [i:i] = "": [i1].Resize(k) = jg1: [i1].EntireColumn.AutoFit
  132.         [b15] = [b15] & " " & Format(Timer - tms, "0.000s")
  133.     End If
  134.     Erase jg1
  135. End Sub
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-17 07:36 , Processed in 0.044017 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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