|
楼主 |
发表于 2013-1-14 20:59
|
显示全部楼层
本帖最后由 香川群子 于 2013-1-15 09:37 编辑
比如,举个计算例子:
101/102/103/104/105 一共5个数,求和范围[300-320]
用我的代码计算结果是10中组合,这正好是所有5个元素的全部组合=combin(5,3)=10
+105+104+101 = 310
+105+104+102 = 311
+105+104+103 = 312
+105+103+101 = 309
+105+103+102 = 310
+105+102+101 = 308
+104+103+101 = 308
+104+103+102 = 309
+104+102+101 = 307
+103+102+101 = 306
重新贴一遍,最好的、功能最全的递归组合计算代码如下:
- Dim sj, jg(), m%, n%, k&, h&, h2& '定义公用变量,以便递归过程使用
- Sub kagawa_4()
- h = [b1]: h2 = [b2]: If h2 > h Then h2 = h2 - h '设定和值范围为B1单元格和B2单元格之间,如B2单元格为空则只考虑=B1单元格值
- m = [a1].End(4).Row: ' sj0 = [a1].Resize(m)
- [a1].Resize(m).Sort [a1], 1, , , 2 '原始数据排序
- sj = [a1].Resize(m, 2): ' [a1].Resize(m) = sj0
- If [b3] > 0 And [b3] <= m Then n = [b3] Else n = 0 '如果B3单元格为空则计算所有组合,否则仅返回指定个数=n的结果
-
- sj(1, 2) = sj(1, 1)
- For i = 2 To m
- sj(i, 2) = sj(i - 1, 2) + sj(i, 1) '整理累计和 以便进行次位【累計和】快速剪枝
- Next
-
- ReDim jg(65535, 2): jg(0, 0) = "n": jg(0, 1) = "s": jg(0, 2) = "dgH4: "
- k = 0: cnt = 0: tms = Timer '初始化
-
- Call dgH4(h, "", m + 1, 1) '调用递归过程开始计算直至结束
-
- MsgBox "Result: " & k & " Time: " & Format(Timer - tms, "0.000s")
- If k > 0 And k < 65536 Then [f:h] = "": [f1].Resize(k + 1, 3) = jg
- If ActiveWorkbook.ActiveSheet.FilterMode = False Then [f1].CurrentRegion.AutoFilter
- [h1] = "dgH4: " & k
- End Sub
- '下面是递归过程: 逆序递归差値計算、正序検索末位=[r,r+h2]、次位>r+h2时剪枝停止/次位累計和<r时剪枝停止
- Sub dgH4(r, s$, i%, t%)
- '递归过程 r=对于目标和值的递减差值,s=过程的文字结果记录,i=倒序检查位置,t=累计参与计算元素个数
- Dim j%
-
- If n = 0 Or t = n Then
- For j = 1 To i - 1 '正序検索
- If r <= sj(j, 1) And sj(j, 1) <= r + h2 Then '正序検索末位范围=[r,r+h2]
- k = k + 1 '符合目标和值范围时即可将此结果写入数组
- If k < 65536 Then
- jg(k, 0) = t
- jg(k, 1) = h - r + sj(j, 1)
- jg(k, 2) = s & "+" & sj(j, 1)
- End If
- End If
- Next
- End If
- If t = n Then Exit Sub 'n=0时即无个数限制则继续
-
- For j = i - 1 To 2 Step -1 '逆序递归
- If sj(j, 1) < r + h2 Then '次位>r+h2时剪枝停止
- If sj(j, 2) < r Then
- Exit For '次位【累計和】sj(j,2)<r时剪枝停止
- Else
- Call dgH4(r - sj(j, 1), s & "+" & sj(j, 1), j, t + 1) '递归差値計算
- End If
- End If
- Next
- End Sub
复制代码 |
|