【求助】求特定和值的数字组合
excel吧
全部回复
仅看楼主
level 11
tmxzp 楼主
如下图,B列基础数据,第一行是目标数字(A列是辅助列)
我需要在C~F列自动找出和值最接近目标数字的组合,且只能大于目标数字
用过C2=IF(SUM(C$2:C$29)=B$2,C$1,A2*RANDBETWEEN(0,1)),启用迭代,但是发现要经过几十次上百次的刷新,才能算出第一组结果,还不如肉眼看的快。
也尝试过用“规划求解”,但是运算出来的结果都是小数,即每个数取一点点,然后组合成目标数字,不知道是不是我的设置不对
还请大神指教一二,
感谢
2022年12月06日 13点12分 1
level 11
用过的数据还能用吗?
2022年12月06日 14点12分 2
不能,数据只能用一次
2022年12月06日 14点12分
@tmxzp 源数据量大概有多少,你这里是28个。
2022年12月06日 14点12分
@🌴菠萝蜜🌴 最多应该不超过40
2022年12月06日 14点12分
@tmxzp 40个数据应该压力不大,自己测试一下。
2022年12月06日 14点12分
level 8
我怎么会想到背包问题[捂嘴笑]
2022年12月06日 14点12分 3
level 11
'每个数使用一次,不太可能是最优但接近于最优应该是没有问题的
'自己对结果进行分拆一下就可以了
Option Explicit
Sub abc()
 Dim a, b, i, j, k, m, t, cnt, n
 a = Range("b2:b" & [b2].End(xlDown).Row)
 b = [c1].Resize(, [c1].End(xlToRight).Column - 2).Value
 ReDim d(1 To 1, 1 To UBound(b, 2))
 Call bsort(a, 1, UBound(a, 1), 1, 1, 1)
 cnt = UBound(a)
 ReDim c(1 To 2, 1 To 2)
 For i = 1 To UBound(b, 2)
  c(1, 1) = vbNullString: c(1, 2) = 10 ^ 8
  Call combin(a, c, 0, LBound(a, 1), cnt, 0, b(1, i), vbNullString)
  d(1, i) = c(1, 1)
  t = Split(c(1, 1), "+")
  For j = 1 To UBound(t)
   For k = 1 To cnt
    If CStr(a(k, 1)) = t(j) Then a(k, 1) = vbNullString: Exit For
   Next
  Next
  For j = 1 To cnt
   If Len(a(j, 1)) Then m = m + 1: a(m, 1) = a(j, 1)
  Next
  cnt = m: m = 0
 Next
 [c2].Resize(, UBound(d, 2)) = d
End Sub
Function bsort(a, first, last, left, right, key)
 Dim i, j, k, t
 For i = first To last - 1
  For j = first To last + first - 1 - i
   If a(j, key) < a(j + 1, key) Then
    For k = left To right
     t = a(j, k): a(j, k) = a(j + 1, k): a(j + 1, k) = t
    Next
   End If
  Next
 Next
End Function
Function combin(a, b, m, n, cnt, t, sum, s)
 If t = sum Then m = m + 1: b(m, 1) = s: Exit Function
 If m = 1 Then Exit Function
 If n > cnt Then Exit Function
 If t > sum Then
  If t - sum < b(1, 2) Then b(1, 2) = t - sum: b(1, 1) = s
  Exit Function
 Else
  If sum - t < b(1, 2) Then b(1, 2) = sum - t: b(1, 1) = s
 End If
 Call combin(a, b, m, n + 1, cnt, t, sum, s)
 Call combin(a, b, m, n + 1, cnt, t + a(n, 1), sum, s & "+" & a(n, 1))
End Function
2022年12月06日 14点12分 4
不会vba[泪]
2022年12月06日 14点12分
@tmxzp 我也不会公式 [咦]
2022年12月06日 14点12分
@- 我这就是一个for+rec调用的,只是和数多余一个而且用过的数是不能再次使用的,那就要处理,代码会啰嗦一点的。
2022年12月07日 02点12分
@- 这是一个规模问题,源数据就算40个,暴力单个求和最坏的计算量为1->2^40-1的,所以会对源数据先做有序处理这样效率会高得多的,这里就先冒了泡,因为源数据不一定是有序的。求多个和值估计还不太好使用自定义函数,因为对用过的数不太好处理,而且效率估计也够呛。
2022年12月07日 03点12分
1