最高金额 [英] Highest possible sum

查看:57
本文介绍了最高金额的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在A列中有一个项目列表,并且每个项目在后续列中都有10个不同的值.我需要创建一个公式(或者最有可能超过一个公式),该公式将返回最大可能的10个值的总和(每个列中的一个),并限制每个项目最多只能使用一次.我还需要使用这些物品的订单.我正试图通过几个步骤做到这一点:

I have a list of items in column A and each of this items has 10 different values in subsequent columns. I need to create a formula (or most probably more than one formula) that would return the highest possible sum of 10 values (one from each column) with a restriction that each item can be used one time at most. I would also need an order in which those items were used. I was trying to do it in a few steps:

第1步:检查B列中的最大值.

Step 1: Check the highest value in column B.

第2步:检查C列中的最大值.

Step 2: Check the highest value in column C.

第3步:如果这是同一项目,则在B和C列中找到第二高的值,并检查哪个总和更高(B的第一位和C的第二位或其他方式).

Step 3: If this is the same item then find the second highest value for columns B and C and check which sum is higher (1st of B and second of C or other way around).

但是,在极少数情况下,此算法会给出错误的输出,并且由于我需要为每列添加10个不同值的比较,因此该公式呈指数增长.如果有一天我试图扩展值的数量,那将很麻烦.如果您看到更好的解决方案,请告诉我.我不介意是否需要VBA.

This algorithm however in rare cases gives incorrect output and the formula grows exponentially as I need to add comparison for 10 different values for each column. It would be quite bothersome if I tried to expand the number of values someday. If you see a better solution please let me know. I wouldn't mind if that would need VBA.

推荐答案

下面的VBA宏假定项目名称在 A列中,值在 B到K列,则 Row 1 是标题,并且值是 Long (即无小数点)

The following VBA macro assumes that the Item Name is in Column A, the Values are in Columns B to K, that Row 1 is a header, and that the Values are Long (i.e. no Decimal points)

这是一种效率低下的蛮力方法.对于10个项目,大约需要2分钟才能计算出来.对于11个项目,大约需要7.5分钟,以此类推-由于增长将成倍增长,因此您希望在运行它之前先减少可能的答案.(例如,每列的项目将从该列的前10个值中提取-因此,您可以删除任何列的前10个未出现的项目)

This is an inefficient brute-force method. For 10 items, it takes about 2 minutes to calculate. For 11 items, it takes about 7.5 minutes, etc - since growth will be exponential, you will want to pare down the possible answers before you run it. (e.g. the Item for each column will be taken from the top 10 Values for that column - so, you can delete any item that doesn't appear in the top 10 for any column)

Option Explicit

Sub VeryLongBruteForceMethod()
    Dim Screen As Boolean, Calc As XlCalculation, Mouse As XlMousePointer
    Mouse = Application.Cursor
    Application.Cursor = xlDefault
    Screen = Application.ScreenUpdating
    Calc = Application.Calculation
    Application.Cursor = xlWait
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    'Row / Value for each column
    Dim MaxItems(0 To 9, 0 To 1) As Long, lMaxVal As Long
    Dim TestItems(0 To 9, 0 To 1) As Long, lTestVal As Long
    Dim lMaxRow As Long, lTestRow As Long, bTest As Boolean
    Dim lCol0 As Long, lCol1 As Long, lCol2 As Long, lCol3 As Long, lCol4 As Long
    Dim lCol5 As Long, lCol6 As Long, lCol7 As Long, lCol8 As Long, lCol9 As Long
    Dim wsTarget As Worksheet

    Set wsTarget = ThisWorkbook.Worksheets(1) 'First sheet in Workbook

    lMaxRow = wsTarget.Cells(wsTarget.Rows.Count, 1).End(xlUp).Row 'Get Row for last item
    lMaxVal = 0
    For lCol0 = 2 To lMaxRow 'Assumes Row1 is a header
        TestItems(0, 0) = lCol0 'Store row
        TestItems(0, 1) = wsTarget.Cells(lCol0, 2).Value 'Store value
        For lCol1 = 2 To lMaxRow 'Assumes Row1 is a header
            bTest = True
            If lCol1 = lCol0 Then bTest = False 'Row already used in this permutation
            If bTest Then
                TestItems(1, 0) = lCol1 'Store row
                TestItems(1, 1) = wsTarget.Cells(lCol1, 3).Value 'Store value
                For lCol2 = 2 To lMaxRow 'Assumes Row1 is a header
                    bTest = True
                    For lTestRow = 0 To 1
                        If TestItems(lTestRow, 0) = lCol2 Then
                            bTest = False  'Row already used in this permutation
                            Exit For '1 failure is enough
                        End If
                    Next lTestRow
                    If bTest Then
                        TestItems(2, 0) = lCol2 'Store row
                        TestItems(2, 1) = wsTarget.Cells(lCol2, 4).Value 'Store value
                        For lCol3 = 2 To lMaxRow 'Assumes Row1 is a header
                            bTest = True
                            For lTestRow = 0 To 2
                                If TestItems(lTestRow, 0) = lCol3 Then
                                    bTest = False  'Row already used in this permutation
                                    Exit For '1 failure is enough
                                End If
                            Next lTestRow
                            If bTest Then
                                TestItems(3, 0) = lCol3 'Store row
                                TestItems(3, 1) = wsTarget.Cells(lCol3, 5).Value 'Store value
                                For lCol4 = 2 To lMaxRow 'Assumes Row1 is a header
                                    bTest = True
                                    For lTestRow = 0 To 3
                                        If TestItems(lTestRow, 0) = lCol4 Then
                                            bTest = False  'Row already used in this permutation
                                            Exit For '1 failure is enough
                                        End If
                                    Next lTestRow
                                    If bTest Then
                                        TestItems(4, 0) = lCol4 'Store row
                                        TestItems(4, 1) = wsTarget.Cells(lCol4, 6).Value 'Store value
                                        For lCol5 = 2 To lMaxRow 'Assumes Row1 is a header
                                            bTest = True
                                            For lTestRow = 0 To 4
                                                If TestItems(lTestRow, 0) = lCol5 Then
                                                    bTest = False  'Row already used in this permutation
                                                    Exit For '1 failure is enough
                                                End If
                                            Next lTestRow
                                            If bTest Then
                                                TestItems(5, 0) = lCol5 'Store row
                                                TestItems(5, 1) = wsTarget.Cells(lCol5, 7).Value 'Store value
                                                For lCol6 = 2 To lMaxRow 'Assumes Row1 is a header
                                                    bTest = True
                                                    For lTestRow = 0 To 5
                                                        If TestItems(lTestRow, 0) = lCol6 Then
                                                            bTest = False  'Row already used in this permutation
                                                            Exit For '1 failure is enough
                                                        End If
                                                    Next lTestRow
                                                    If bTest Then
                                                        TestItems(6, 0) = lCol6 'Store row
                                                        TestItems(6, 1) = wsTarget.Cells(lCol6, 8).Value 'Store value
                                                        For lCol7 = 2 To lMaxRow 'Assumes Row1 is a header
                                                            bTest = True
                                                            For lTestRow = 0 To 6
                                                                If TestItems(lTestRow, 0) = lCol7 Then
                                                                    bTest = False  'Row already used in this permutation
                                                                    Exit For '1 failure is enough
                                                                End If
                                                            Next lTestRow
                                                            If bTest Then
                                                                TestItems(7, 0) = lCol7 'Store row
                                                                TestItems(7, 1) = wsTarget.Cells(lCol7, 9).Value 'Store value
                                                                For lCol8 = 2 To lMaxRow 'Assumes Row1 is a header
                                                                    bTest = True
                                                                    For lTestRow = 0 To 7
                                                                        If TestItems(lTestRow, 0) = lCol8 Then
                                                                            bTest = False  'Row already used in this permutation
                                                                            Exit For '1 failure is enough
                                                                        End If
                                                                    Next lTestRow
                                                                    If bTest Then
                                                                        TestItems(8, 0) = lCol8 'Store row
                                                                        TestItems(8, 1) = wsTarget.Cells(lCol8, 10).Value 'Store value
                                                                        For lCol9 = 2 To lMaxRow 'Assumes Row1 is a header
                                                                            bTest = True
                                                                            For lTestRow = 0 To 8
                                                                                If TestItems(lTestRow, 0) = lCol9 Then
                                                                                    bTest = False  'Row already used in this permutation
                                                                                    Exit For '1 failure is enough
                                                                                End If
                                                                            Next lTestRow
                                                                            If bTest Then
                                                                                TestItems(9, 0) = lCol9 'Store row
                                                                                TestItems(9, 1) = wsTarget.Cells(lCol9, 11).Value 'Store value
                                                                                lTestVal = 0
                                                                                'Application.StatusBar = lCol0 & "|" & lCol1 & "|" & lCol2 & "|" & lCol3 & "|" & lCol4 & "|" & lCol5 & "|" & lCol6 & "|" & lCol7 & "|" & lCol8 & "|" & lCol9
                                                                                For lTestRow = 0 To 9 'Total up our Value
                                                                                    lTestVal = lTestVal + TestItems(lTestRow, 1)
                                                                                Next lTestRow
                                                                                If lTestVal > lMaxVal Then 'Compare to current Max
                                                                                    For lTestRow = 0 To 9 'If more, replace with new Max
                                                                                        MaxItems(lTestRow, 0) = TestItems(lTestRow, 0)
                                                                                        MaxItems(lTestRow, 1) = TestItems(lTestRow, 1)
                                                                                    Next lTestRow
                                                                                    lMaxVal = lTestVal
                                                                                End If
                                                                            End If
                                                                        Next lCol9
                                                                    End If
                                                                Next lCol8
                                                            End If
                                                        Next lCol7
                                                    End If
                                                    DoEvents ' Try not to let Excel crash on us!
                                                Next lCol6
                                            End If
                                        Next lCol5
                                    End If
                                Next lCol4
                            End If
                        Next lCol3
                    End If
                Next lCol2
            End If
        Next lCol1
    Next lCol0
    'Output to a message box:
    'Column 1: ItemName01 | Value01
    ' ...
    'Column 10: ItemName10 | Value10
    'Total Value | TotalValue
    Dim sOutput As String
    sOutput = ""
    For lTestRow = 0 To 9
        sOutput = sOutput & "Column " & (lTestRow + 1) & ": " & wsTarget.Cells(MaxItems(lTestRow, 0), 1).Value & " | " & MaxItems(lTestRow, 1) & vbCrLf
    Next lTestRow
    sOutput = sOutput & "Total Value | " & lMaxVal
    MsgBox sOutput

    Erase TestItems
    Erase MaxItems
    Application.StatusBar = False
    Application.Cursor = Mouse
    Application.Calculation = Calc
    Application.ScreenUpdating = Screen
End Sub

这篇关于最高金额的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆