一组中的数字组合加起来给定总数

时间:2014-01-31 06:44:17

标签: vba vb6

我一直在寻找一个数学问题的解决方案

我修复了一组数字 [65536,131072,262144,524288,104576,2097152]

我将只有一些以上数字

但我的问题是如何在给定总数中得到数字组合?

请帮帮我PLZ

2 个答案:

答案 0 :(得分:1)

我的解决方案与戴维斯非常相似。

假设:这组数字按升序排列。

调用该函数并从最高编号开始,传递一个空的部分解决方案并尝试计算返回总数的所有可能的数字总和。总和作为集合返回。

功能:

  1. 创建一个列表以容纳所有解决方案
  2. 测试集合中的每个数字(从传递的numberSetIndex开始并向下移动):
    1. if number > total然后跳到下一个数字
    2. 将数字附加到部分解决方案
    3. if number = total然后将此部分解决方案添加到列表中并转到下一个数字
    4. 如果number < total那么
      1. 再次调用此函数(使用total -= number和部分解决方案的副本,以及当前的数字索引)
      2. 追加所有已退回的解决方案
  3. 返回所有解决方案
  4. 注意:我不明白你是否只想使用该组的每个数字一次,所以下面的代码也将计算包含多个数字实例的总和在给定的集合中。
    如果您希望每个数字只出现一次,请找到行
    Set result = AllSumsForTotalFromSet(total - number, numberSet, index, CopyAndReDimPlus1(partialSolution))
    在函数Function AllSumsForTotalFromSet中,并在递归调用中将index替换为index-1

    Sub Test_AllSumsForTotalFromSet()
        Dim numberSet, total As Long, result As Collection
    
        numberSet = Array(65536, 131072, 262144, 524288, 104576, 2097152)
        total = 366720
    
        Set result = GetAllSumsForTotalFromSet(total, numberSet)
    
        Debug.Print "Possible sums: " & result.count
    
        PrintResult result
    End Sub
    
    Function GetAllSumsForTotalFromSet(total As Long, ByRef numberSet As Variant) As Collection
        Set GetAllSumsForTotalFromSet = New Collection
        Dim partialSolution(1 To 1) As Long
    
        Set GetAllSumsForTotalFromSet = AllSumsForTotalFromSet(total, numberSet, UBound(numberSet), partialSolution)
    End Function
    
    Function AllSumsForTotalFromSet(total As Long, ByRef numberSet As Variant, numberSetIndex As Long, ByRef partialSolution() As Long) As Collection
        Dim index As Long, number As Long, result As Collection
    
        Set AllSumsForTotalFromSet = New Collection
    
        'break if numberSetIndex is too small
        If numberSetIndex < LBound(numberSet) Then Exit Function
    
        For index = numberSetIndex To LBound(numberSet) Step -1
            number = numberSet(index)
    
            If number <= total Then
                'append the number to the partial solution
                partialSolution(UBound(partialSolution)) = number
    
                If number = total Then
                    AllSumsForTotalFromSet.Add partialSolution
    
                Else
                    Set result = AllSumsForTotalFromSet(total - number, numberSet, index, CopyAndReDimPlus1(partialSolution))
                    AppendCollection AllSumsForTotalFromSet, result
                End If
            End If
        Next index
    End Function
    
    'copy the passed array and increase the copy's size by 1
    Function CopyAndReDimPlus1(ByVal sourceArray As Variant) As Long()
        Dim i As Long, destArray() As Long
        ReDim destArray(LBound(sourceArray) To UBound(sourceArray) + 1)
    
        For i = LBound(sourceArray) To UBound(sourceArray)
            destArray(i) = sourceArray(i)
        Next i
    
        CopyAndReDimPlus1 = destArray
    End Function
    
    'append sourceCollection to destCollection
    Sub AppendCollection(ByRef destCollection As Collection, ByRef sourceCollection As Collection)
        Dim e
        For Each e In sourceCollection
            destCollection.Add e
        Next e
    End Sub
    
    Sub PrintResult(ByRef result As Collection)
        Dim r, a
    
        For Each r In result
            For Each a In r
                Debug.Print a;
            Next
            Debug.Print
        Next
    End Sub
    

答案 1 :(得分:0)

有趣的思想实验......这是我的解决方案(预警 - 没有代码,只有算法)

  1. 按顺序排列
  2. 使用树/节点结构
  3. 编写遍历列表的递归循环。如果它所处的值小于剩余值,则将该值添加为子项
  4. 如果它所处的值等于剩余总数,请将该值添加为子项并标记为解决方案
  5. 如果它所处的值大于剩余总数,则将分支标​​记为不可解决
  6. 如果到达列表末尾,请将该分支标记为不可解决
  7. 您最终应该得到一张代表有效解决方案的树。例如:

    set = [50,40,30,20,15,10,5]
    total required = 60
    Solution tree
    root
        50 -> 10
        40 -> 20
           -> 15 -> 5
        30 -> 20 -> 10
           -> 15 -> 10 -> 5