所以,我需要找到10个数据点列表的组合总数,这些数据点加起来至少为100个。所有解决这个问题的例子我发现只给出EQUAL数字的组合数量。如何计算高于100的组合?如果没有Excel中的VBA,这可行吗?
另一个想法是计算组合总数(10!)并减去1,000以下的组合来查找数字。但同样,如何找到落在某个范围内的组合总数?
问题陈述:10个数据点(65,52,48,44,42,41,39,38,30,18)总共至少有100个组合?
我尝试过的来源(我不能发布2个以上的链接) http://www.tushar-mehta.com/excel/templates/match_values/index.html
Find out which combinations of numbers in a set add up to a given total
答案 0 :(得分:3)
=IF(ROW()<512,"0" & DEC2BIN(ROW(),9),"1" & DEC2BIN(ROW()-512,9))
=SUMPRODUCT((A1:J1)*(M1:V1))
并复制列 W 包含所有可能组合的总和。
最后,在另一个单元格中输入:
=COUNTIF(W:W,">=" & 100)
修改#1:强>
要生成 36 位二进制模式,我使用:
=DEC2BIN(INT(ROW()/2^27),9)&DEC2BIN(INT(MOD(ROW(),2^27)/2^18),9)&DEC2BIN(INT(MOD(ROW(),2^18)/2^9),9)&DEC2BIN(MOD(ROW(),2^9),9)
因此,对于 20 位,只需使用:
=RIGHT(DEC2BIN(INT(ROW()/2^27),9)&DEC2BIN(INT(MOD(ROW(),2^27)/2^18),9)&DEC2BIN(INT(MOD(ROW(),2^18)/2^9),9)&DEC2BIN(MOD(ROW(),2^9),9),20)
修改#2:强>
要使用VBA执行 TextToColumns 之类的操作,请选择单元格并运行此宏:
Sub PseudoTextToColumns()
Dim r As Range, L As Long, i As Long, t As String
For Each r In Selection
t = r.Text
L = Len(t)
For i = 1 To L
r.Offset(0, i).Value = Mid(t, i, 1)
Next i
Next r
End Sub
<强> 注:的强>
这不适用于21件物品。
答案 1 :(得分:1)
VBA强力解决方案
我会分享以下强力解决方案,检查所有可能的组合。它在小型阵列上足够快,最多可达15个条目。它解决了您的问题,您可以将其作为任何粗暴计算的模型,也可以作为优化和应用更快算法的起点。它也可以作为测试您稍后可能实现的任何优化算法的良好基础。
Option Explicit
' Main function. Computes the all combinations and prints those that exceed the target
' Each combination is specified by a mask of bits that specifies whether to take o to leave the entry
Function CombinationsByBruteForce(inputArray() As Double, target As Double) As Long
Dim mask As Long, count As Long
For mask = 1 To 2 ^ (1 + UBound(inputArray)) - 1
If SumByMask(inputArray, mask) > target Then
count = count + 1
PrintByMask inputArray, mask
End If
Next
Debug.Print "Total number of successful combinations: " & count
CombinationsByBruteForce = count
End Function
' computes the sum for a given combination. The combination is specified by a mask of bits
' that tells which entries belong to the combination (the 1 bits)
Function SumByMask(inputArray() As Double, mask As Long) As Double
Dim bit As Long
For bit = 0 To UBound(inputArray)
If (mask And (2 ^ bit)) <> 0 Then SumByMask = SumByMask + inputArray(bit)
Next
End Function
' Prints out the entries belonging to a combination specified by a mask
Sub PrintByMask(inputArray() As Double, mask As Long)
Dim bit As Long
For bit = 0 To UBound(inputArray)
If (mask And (2 ^ bit)) <> 0 Then Debug.Print inputArray(bit),
Next
Debug.Print
End Sub
' For testing. An array of doubles and a target are specified.
' The variant array is copied into a Double array to improve speed
Sub testing()
Dim target As Double: target = 350 ' target number to exceed
Dim test: test = Array(65, 52, 48, 44, 42, 41, 39, 38, 30, 18)
'convert to explicit array of Double
ReDim inputArray(UBound(test)) As Double
Dim i As Long
For i = LBound(test) To UBound(test): inputArray(i) = test(i): Next
' Launsh the brute force computation
CombinationsByBruteForce inputArray, target
End Sub
上述测试的输出:
65 52 48 44 42 41 39 38 65 52 48 44 42 41 39 30 65 52 48 44 42 41 38 30 65 52 48 44 42 39 38 30 65 52 48 44 41 39 38 30 65 52 48 42 41 39 38 30 65 52 44 42 41 39 38 30 65 52 48 44 42 41 39 38 30 65 52 48 44 42 41 39 38 18 65 52 48 44 42 41 39 30 18 65 52 48 44 42 41 38 30 18 65 52 48 44 42 39 38 30 18 65 52 48 44 41 39 38 30 18 65 52 48 42 41 39 38 30 18 65 52 44 42 41 39 38 30 18 65 48 44 42 41 39 38 30 18 52 48 44 42 41 39 38 30 18 65 52 48 44 42 41 39 38 30 18 Total number of successful combinations: 18
作为使用求解器求解的入口点,您可以尝试BIP
模型,其中决策变量是掩码的位。然后,解算器应该应用一些分支和绑定或类似技术来查找组合。但是使用求解器打印出所有成功的组合似乎更难解决,因为它不是优化问题。