我有一个具有正值的数组。例如 array= {5,4,4,3.8,2,1.7} 我需要找到一个总和最大但小于 12 的子数组。在这种情况下,它将是 {4,4,3.8}
另一个 ex 数组 {7,4,3,2} 在这种情况下,最大总和为 12,子集为 {7,3,2}
它的算法是什么,因为我有一个长度超过 1000 的非常大的数组。我正在用 VBA excel 编写这个程序。
谢谢。
我有一个具有正值的数组。例如 array= {5,4,4,3.8,2,1.7} 我需要找到一个总和最大但小于 12 的子数组。在这种情况下,它将是 {4,4,3.8}
另一个 ex 数组 {7,4,3,2} 在这种情况下,最大总和为 12,子集为 {7,3,2}
它的算法是什么,因为我有一个长度超过 1000 的非常大的数组。我正在用 VBA excel 编写这个程序。
谢谢。
试试这个算法的子序列
Sub aargh()
Dim a As Variant
Dim limsum As Double, highestnum As Double
Dim i As Integer, j As Integer
a = Array(5, 4, 4, 3.8, 2, 1.7)
limsum = 12
highestsum = 0
For i = 0 To UBound(a)
s = a(i)
j = i
Do
If s > highestsum Then fs = i: ls = j: highestsum = s
j = j + 1
If j > UBound(a) Then Exit Do
s = s + a(j)
Loop While s <= limsum
Next i
MsgBox "subarray (" & fs & "," & ls & ") sum = " & highestsum
End Sub
编辑以包括以下备注并包括子集的解决方案
Sub aargh()
Dim sol(), csol()
a = Array(7, 4, 3, 2)
ReDim sol(LBound(a) To UBound(a))
ReDim csol(LBound(a) To UBound(a))
limsum = 13
findsum a, sol, csol, maxsum, limsum
ss = "array "
For i = 1 To sol(0)
ss = ss & sep & a(sol(i))
sep = ","
Next i
MsgBox ss & " sum =" & maxsum
End Sub
Sub findsum(ByRef a, ByRef sol, ByRef csol, ByRef maxsum, ByRef limsum, Optional s = 0, Optional lvl = 1, Optional si = 0)
' recursive sub
For i = si To UBound(a)
s = s + a(i)
csol(lvl) = i ' current solution contains number i
If s <= limsum Then
If s > maxsum Then ' we found a sum greater than current max we save it
maxsum = s
sol(0) = lvl
For j = 1 To lvl
sol(j) = csol(j)
Next j
End If
If i < UBound(a) Then ' pick another number
findsum a, sol, csol, maxsum, limsum, s, lvl + 1, i + 1
End If
End If
s = s - a(i)
Next i
End Sub
如果数组已排序(降序),则代码优化
Sub aargh()
Dim sol(), csol()
a = Array(20, 15, 10, 7, 6, 5, 4, 3, 2)
ReDim sol(LBound(a) To UBound(a))
ReDim csol(LBound(a) To UBound(a))
limsum = 13
findsum a, sol, csol, maxsum, limsum, UBound(a)
ss = "array "
For i = 1 To sol(0)
ss = ss & sep & a(sol(i))
sep = ","
Next i
MsgBox ss & " sum =" & maxsum
End Sub
Sub findsum(ByRef a, ByRef sol, ByRef csol, ByRef maxsum, ByRef limsum, si, Optional s = 0, Optional lvl = 1)
' recursive sub
For i = si To LBound(a) Step -1
If s + a(i) > limsum Then Exit For
s = s + a(i)
csol(lvl) = i ' current solution contains number i
If s <= limsum Then
If s > maxsum Then ' we found a sum greater than current max we save it
maxsum = s
sol(0) = lvl
For j = 1 To lvl
sol(j) = csol(j)
Next j
End If
If i > LBound(a) Then ' pick another number
findsum a, sol, csol, maxsum, limsum, i - 1, s, lvl + 1
End If
End If
s = s - a(i)
If maxsum = limsum Then Exit For 'exit if exact match
Next i
End Sub
正如多人在评论中提到的那样,这是子集和问题的简单变体。为了解决这个确切的问题,你只需要记住你发现的小于或等于的最大数12
。
一个简单的递归abroach如下:
list = [...]
N = length of list
dp[ maximum possible sum ][ N ]
f(current_sum, index):
if dp[current_sum][index] is set
return dp[current_sum][index]
if index >= N
if current_sum > 12
result = 0
else
result = current_sum
else
result = max( f(current_sum, index+1), f(current_sum+list[index], index+1)
dp[current_sum][index] = result
return result
result = f(0,0) // this will return the desired result