|
Option Explicit
Sub test()
Dim vResult(), ar, br, cr, vTemp, r&, i&, j&, m&, n&, iCol&, bytDigit As Byte, dic As Object, vKey, t#
Application.ScreenUpdating = False
t = Timer
bytDigit = 0
iCol = 5
r = Cells(Rows.Count, "A").End(xlUp).Row
vTemp = Range("A2:E" & r).Value
ar = Application.Index(vTemp, , iCol)
ReDim Preserve ar(1 To UBound(ar), 1 To 2)
For i = 1 To UBound(ar): ar(i, 2) = i: Next i
bSort ar, 1, UBound(ar), 1, 2
n = UBound(ar)
ReDim br(1 To n)
r = 0
MakeNumCount vResult, ar, br, r, 28, bytDigit
Set dic = CreateObject("Scripting.Dictionary")
n = 0
Columns("G:XFD").Clear
If r Then
ReDim ar(1 To UBound(vResult, 2), 1 To 2)
For i = 1 To UBound(vResult, 2)
ar(i, 1) = vResult(1, i)
ar(i, 2) = vResult(2, i)
Next i
ShellSort2D ar, 1, UBound(ar), 1, 2, 1
For i = 1 To UBound(ar)
dic(ar(i, 1)) = dic(ar(i, 1)) & "|" & ar(i, 2)
Next i
For Each vKey In dic.keys
n = n + 1
br = Split(dic(vKey), "|")
m = 1
ReDim ar(1 To UBound(br) * (vKey + 1), 0)
ar(m, 0) = vKey & "个相加结果等于28"
For i = 1 To UBound(br)
cr = Split(br(i), ",")
For j = 0 To UBound(cr)
m = m + 1
ar(m, 0) = vTemp(cr(j), 1)
Next j
If i < UBound(br) Then m = m + 1
Next i
Cells(1, n + 6).Resize(m) = ar
Columns(n + 6).AutoFit
Next
End If
Application.ScreenUpdating = True
MsgBox "执行完毕!_用时: " & Format(Timer - t, "0.00") & " 秒,共发现 " & r & " 组", 64
End Sub
Function MakeNumCount(ByRef vResult(), ByVal ar, ByVal br, ByRef iGroup&, ByVal iSum&, ByVal bytDigit As Byte, Optional ByVal iCount& = 0, _
Optional ByVal iEleNum& = 0, Optional ByVal iTemp& = 0, Optional ByVal iStart& = 1, Optional ByVal iChkNum& = -1)
Dim i&, j&, iNum&, cr(), strJoin$, r&, m&
iChkNum = iChkNum + 1
If iEleNum * (iEleNum = iChkNum) Then Exit Function
For i = iStart To UBound(br)
If iCount * (iGroup = iCount) Then Exit Function
iNum = ar(i, 1) * 10 ^ bytDigit: br(i) = iNum
If iTemp + iNum > iSum Then Exit Function
If iTemp + iNum = iSum Then
r = 0: strJoin = ""
For j = 1 To UBound(br)
If br(j) <> "" Then
strJoin = strJoin & IIf(br(j) < 0, "", "+") & br(j) * 10 ^ -bytDigit
r = r + 1
ReDim Preserve cr(1 To r)
cr(r) = ar(j, 2)
End If
Next j
m = IIf(iEleNum = 0, r, iEleNum)
If r = m Then
iGroup = iGroup + 1
ReDim Preserve vResult(1 To 2, 1 To iGroup)
vResult(1, iGroup) = r
vResult(2, iGroup) = Join(cr, ",")
End If
ElseIf iTemp + iNum < iSum Then
Call MakeNumCount(vResult, ar, br, iGroup, iSum, bytDigit, iCount, iEleNum, iTemp + iNum, i + 1, iChkNum)
End If
br(i) = ""
Next i
End Function
Function bSort(ar, iFirst&, iLast&, iLeft&, iRight&, _
Optional iKey& = 1, Optional isOrder As Boolean = True)
Dim i&, j&, k&, vTemp
For i = iFirst To iLast - 1
For j = iFirst To iLast + iFirst - 1 - i
If ar(j, iKey) <> ar(j + 1, iKey) Then
If ar(j, iKey) < ar(j + 1, iKey) Xor isOrder Then
For k = iLeft To iRight
vTemp = ar(j, k)
ar(j, k) = ar(j + 1, k)
ar(j + 1, k) = vTemp
Next
End If
End If
Next j
Next i
End Function
Function ShellSort2D(ByRef ar, ByVal iFirst&, ByVal iLast&, ByVal iLeft&, _
ByVal iRight&, ByVal iKey&, Optional isOrder As Boolean = True)
Dim iRowSize&, vTemp, interval&, i&, j&, k&
ReDim vTemp(iLeft To iRight)
iRowSize = iLast - iFirst + 1
interval = 1
If iRowSize > 13 Then
Do While interval < iRowSize
interval = interval * 3 + 1
Loop
interval = interval \ 9
End If
Do While interval
For i = iFirst + interval To iLast
For j = iLeft To iRight
vTemp(j) = ar(i, j)
Next
If isOrder Then
For k = i - interval To iFirst Step -interval
If ar(k, iKey) <= vTemp(iKey) Then Exit For
For j = iLeft To iRight
ar(k + interval, j) = ar(k, j)
Next j
Next k
Else
For k = i - interval To iFirst Step -interval
If ar(k, iKey) > vTemp(iKey) Then Exit For
For j = iLeft To iRight
ar(k + interval, j) = ar(k, j)
Next j
Next k
End If
For j = iLeft To iRight
ar(k + interval, j) = vTemp(j)
Next
Next i
interval = interval \ 3
Loop
End Function
|
|