|
本帖最后由 win2009 于 2012-9-30 20:11 编辑
经典啊,高手,又学一招,学习啊
还是这样看方便
Public sj, jg(), m, n, k, jg2(), h1, h2, cnt
Sub kagawa()
tms = Timer
m = [a1].End(4).Row - 1: n = [b5]: h1 = [b2]: h2 = [b3]
sj0 = [a2].Resize(m): [a2].Resize(m).Sort [a2], 1, , , 2
sj = [a2].Resize(m)
[a2].Resize(m) = sj0
If n > m Then AC = 65536 Else AC = WorksheetFunction.Combin(m, n)
If AC > 65535 Then ReDim jg(65535, n) Else ReDim jg(AC, n)
k = 1: cnt = 0
Call bcfhdg("", 0, 0, 0)
jg(0, 0) = "Summary": For i = 1 To n: jg(0, i) = "n" & i: Next
[e1].CurrentRegion = "": If k > 1 Then [e1].Resize(k, n + 1) = jg
[d1] = "<= " & h & " Detail: " & cnt - 1
[e1].Resize(, n + 2).EntireColumn.AutoFit
MsgBox "Calc " & cnt - 1 & " ,Get " & k - 1 & " result." & vbCr & Format(Timer - tms, "0.000s")
End Sub
Sub bcfhdg(s, r, i, t%)
cnt = cnt + 1
p = Split(s, "+")
For j = 1 To UBound(p)
jg(0, j) = p(j)
Next
If r >= h1 And r <= h2 Then
If n > m Or t = n Then
For j = 1 To UBound(p)
jg(k, j) = p(j)
Next
jg(k, 0) = "=" & Mid(s, 2)
k = k + 1
End If
End If
If t = n Then Exit Sub
For j = i + 1 To m
If r + sj(j, 1) > h2 Then Exit For 如果本次递归结果的和值已经大于总和目标范围上限,则可退出循环了。
If CStr(sj(j, 1)) <> jg(0, t + 1) Then
If t < n - 1 Then jg(0, t + 2) = ""
Call bcfhdg(s & "+" & sj(j, 1), r + sj(j, 1), j, t + 1)
End If
Next j
End Sub
公有的 sj ,jg() ,m ,n ,k ,jg2() ,h1 ,h2 ,cnt
过程 kagawa()
tms = 当前计时
m = [a1] . 结束(4) . 行标 - 1: n = [b5]: h1 = [b2]: h2 = [b3]
sj0 = [a2] . 重调大小(m): [a2] . 重调大小(m) . 排序 [a2] ,1 , , ,2
sj = [a2] . 重调大小(m)
[a2] . 重调大小(m) = sj0
如果 n > m 那么 ac = 65536 否则 ac = 工作表公式 . combin(m ,n)
如果 ac > 65535 那么 重定义变量 jg(65535 ,n) 否则 重定义变量 jg(ac ,n)
k = 1: cnt = 0
调用 bcfhdg("" ,0 ,0 ,0)
jg(0 ,0) = "summary": 循环范围 i = 1 到 n: jg(0 ,i) = "n" & i: 下一句
[e1] . 当前区域 = "": 如果 k > 1 那么 [e1] . 重调大小(k ,n + 1) = jg
[d1] = "<= " & h & " detail: " & cnt - 1
[e1] . 重调大小( ,n + 2) . 全部列 . 自动调整
消息框: "calc " & cnt - 1 & " ,读取 " & k - 1 & " result . " & vbcr & 格式化输出(当前计时 - tms ,"0 . 000s")
结束 过程
过程 bcfhdg(s ,r ,i ,t%)
cnt = cnt + 1
p = 分割字符串(s ,"+")
循环范围 j = 1 到 数组上限(p)
jg(0 ,j) = p(j)
下一句
如果 r >= h1 并且 r <= h2 那么
如果 n > m 或者 t = n 那么
循环范围 j = 1 到 数组上限(p)
jg(k ,j) = p(j)
下一句
jg(k ,0) = "=" & 截取字符串(s ,2)
k = k + 1
结束 如果
结束 如果
如果 t = n 那么 退出 过程
循环范围 j = i + 1 到 m
如果 r + sj(j ,1) > h2 那么 退出 循环范围 如果本次递归结果的和值已经大于总和目标范围上限 ,则可退出循环了。
如果 转换为字符串(sj(j ,1))<>jg(0 ,t + 1) 那么
如果 t < n - 1 那么 jg(0 ,t + 2) = ""
调用 bcfhdg(s & "+" & sj(j ,1) ,r + sj(j ,1) ,j ,t + 1)
结束 如果
下一句 j
结束 过程
|
|