ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

四组数据中选五个,VBA如何实现

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-11-13 21:53 | 显示全部楼层
是3^4*4=324

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-11-13 21:56 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

1  4  7   10  11
1  4  7   11   10
就是相同,

TA的精华主题

TA的得分主题

发表于 2012-11-14 08:57 | 显示全部楼层
思考了一下,用嵌套递归,或者说是连续调用递归方法解决了。

  1. Dim sj, sj2(), jg(), m%, n%, k, l%

  2. Sub Combin5() '代码主过程
  3.     tms = Timer
  4.     sj = [a1].CurrentRegion: m = UBound(sj): n = UBound(sj, 2): Amn = m ^ n * n
  5.     If Amn > 65536 Then Exit Sub Else ReDim jg(Amn, n + 3): k = 0
  6.     ReDim sj2(m - 1)
  7.     For l = 1 To n
  8.         Call dgZH("", 0, 0) '调用组合递归过程
  9.     Next
  10.     [a1].Offset(, n + 2).CurrentRegion = "": [a1].Offset(, n + 2).Resize(Amn, n + 4) = jg
  11.     MsgBox k & vbCr & Format(Timer - tms, "0.000s")
  12. End Sub

  13. Sub dgZH(s$, i%, t%) '组合递归过程
  14.     Dim j%
  15.     If t = m - 1 Then
  16.         p = Split(s, ",")
  17.         For j = 1 To m - 1
  18.             sj2(j) = sj(p(j), l)
  19.         Next
  20.         Call dgMN("", 0) '在组合递归过程中调用【香川组合】递归过程
  21.         Exit Sub
  22.     End If
  23.     For j = i + 1 To m
  24.         Call dgZH(s & "," & j, j, t + 1)
  25.     Next j
  26. End Sub

  27. Sub dgMN(s$, t%) '【香川组合】递归过程
  28.     If t = n - 1 Then
  29.         For j = 1 To m - 1
  30.             jg(k, l + j - 1) = sj2(j)
  31. '            jg(k, n + j + 1) = sj2(j)
  32.         Next
  33.         
  34.         p = Split(s, ",")
  35.         For j = 1 To n - 1
  36.             If j < l Then
  37.                 jg(k, j) = sj(p(j), j)
  38.             Else
  39.                 jg(k, j + 2) = sj(p(j), j + 1)
  40.             End If
  41.         Next
  42.         
  43.         jg(k, 0) = jg(k, 1)
  44.         For j = 2 To n + 1
  45.             jg(k, 0) = jg(k, 0) & "," & jg(k, j)
  46.         Next
  47.         
  48.         k = k + 1
  49.         Exit Sub
  50.     End If
  51.     For i = 1 To m
  52.         Call dgMN(s & "," & i, t + 1)
  53.     Next
  54. End Sub
复制代码
附件例子中,用了文字数据。
避免数值大小对组合理解的干扰。

combin5.zip

18.42 KB, 下载次数: 13

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-11-14 09:49 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
谢谢,已经完美解决!!!!!

TA的精华主题

TA的得分主题

发表于 2012-11-14 11:00 | 显示全部楼层
这个问题用VBA数组循环,好像还难以简明解决。

TA的精华主题

TA的得分主题

发表于 2012-11-14 13:23 | 显示全部楼层
香川群子 发表于 2012-11-14 11:00
这个问题用VBA数组循环,好像还难以简明解决。
  1. Dim arr, brr(1 To 3 ^ 5 * 4), crr
  2. Dim a%, b%, c%, d%, e%, f%, x$, s&, s2&, y
  3. arr = Range("a1").CurrentRegion
  4. For a = 1 To 3
  5. For b = 1 To 3
  6. For c = 1 To 3
  7. For d = 1 To 3
  8. x = arr(a, 1) & "," & arr(b, 2) & "," & arr(c, 3) & "," & arr(d, 4)
  9. For e = 1 To 3
  10. For f = 1 To 4
  11.     If InStr("," & x & ",", "," & arr(e, f) & ",") = 0 Then
  12.         s = s + 1
  13.        brr(s) = x & "," & arr(e, f)
  14.     End If
  15. Next f, e, d, c, b, a
  16. ReDim crr(1 To s, 1 To 5)
  17. For i = 1 To s
  18.     x = "," & brr(i) & ","
  19.     For j = i + 1 To s
  20.         y = Split(brr(j), ",")
  21.         For k = 0 To UBound(y)
  22.             x = Replace(x, "," & y(k) & ",", ",")
  23.         Next
  24.         If x = "," Then brr(j) = ""
  25.         x = "," & brr(i) & ","
  26.     Next
  27. Next
  28. For i = 1 To s
  29.     If brr(i) <> "" Then
  30.         s2 = s2 + 1
  31.         z = Split(brr(i), ",")
  32.         For j = 0 To UBound(z)
  33.             crr(s2, j + 1) = z(j)
  34.         Next
  35.     End If
  36. Next
  37. Range("f1").Resize(s2, 5) = crr
复制代码

TA的精华主题

TA的得分主题

发表于 2012-11-14 13:24 | 显示全部楼层
附件…………

1.zip

10.97 KB, 下载次数: 5

TA的精华主题

TA的得分主题

发表于 2012-11-14 15:20 | 显示全部楼层
本帖最后由 香川群子 于 2012-11-14 16:02 编辑
dsmch 发表于 2012-11-14 13:24
附件…………


结果是出来了,但算法不行。
生成全部组合,然后逐个检查比对是否有重复……速度太慢了。

我的递归要比你快 100-200倍。

而且如果原始数据有行数列数增加,你的代码没有通用性无法计算了。


需要考虑好的算法,争取一次性得到不重复结果。
(我的递归已经可以一次性得到结果了,但VBA数组算法还需要挑战。)


TA的精华主题

TA的得分主题

发表于 2012-11-14 16:00 | 显示全部楼层
经研究发现,仅仅对于楼主的特定要求,即【3行4列】,用VBA数组也可以快速解决。

但【超过3行或超过4列】时就无法圆满解决了。(递归代码可以。)
  1. Sub kagawa2()
  2.     tms = Timer
  3.     arr = Range("a1").CurrentRegion
  4.     m = UBound(arr): n = UBound(arr, 2)
  5.     ReDim brr(1 To m ^ n * (m - 1) * n, n + 1): k = 0
  6.     Dim i1%, i2%, i3%, i4%
  7.     For i1 = 1 To m
  8.     For i2 = 1 To m
  9.     For i3 = 1 To m
  10.     For i4 = 1 To m
  11.     For i5 = 1 To m
  12.     For j5 = 1 To n
  13.         If j5 = 1 And i5 <= i1 Then GoTo Nxt
  14.         If j5 = 2 And i5 <= i2 Then GoTo Nxt
  15.         If j5 = 3 And i5 <= i3 Then GoTo Nxt
  16.         If j5 = 4 And i5 <= i4 Then GoTo Nxt
  17.         k = k + 1
  18.         brr(k, 0) = arr(i1, 1) & "," & arr(i2, 2) & "," & arr(i3, 3) & "," & arr(i4, 4) & "," & arr(i5, j5)
  19.         brr(k, 1) = arr(i1, 1)
  20.         brr(k, 2) = arr(i2, 2)
  21.         brr(k, 3) = arr(i3, 3)
  22.         brr(k, 4) = arr(i4, 4)
  23.         brr(k, 5) = arr(i5, j5)
  24. Nxt:
  25.     Next j5, i5, i4, i3, i2, i1
  26.     [a1].Offset(, n + 3).CurrentRegion = ""
  27.     [a1].Offset(, n + 3).Resize(k, n + 2) = brr
  28.     MsgBox k & vbCr & Format(Timer - tms, "0.000s")
  29. End Sub
复制代码

combin5.zip

19.16 KB, 下载次数: 5

TA的精华主题

TA的得分主题

发表于 2012-11-14 20:58 | 显示全部楼层
但【超过3行或超过4列】时就无法圆满解决了
意思是:如果是3行5列的时候,选出6个为一组,每组至少也选一个!就有点困难了吗????
理论上是3^5*5=1215组,用同样的方法,能否实现
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-22 12:33 , Processed in 0.046466 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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