(5/24 更新程式碼,請參考4樓)
(6/28 增加“重複組合功能”,請參考11樓)
這篇有人問,不過提問者自己也是高手,自己有寫程式解決了,我只是提供另一種寫法而己
(離上次回答問題,居然過3年了

http://www.mobile01.com/topicdetail.php?f=511&t=3432008&p=1
這篇也有人問(雖然提問者,主要是要問規劃求解)
http://www.mobile01.com/topicdetail.php?f=511&t=5022284&p=1#62843370
因為2篇標題幾乎一樣
所以把3年前寫的程式,把2^n-1 ,c(n,m) 2個功能合併,
把計算c(n,m)的超多層迴圈,也用副程式代替,縮短程式碼
順便修改一些地方,提升計算速度
第一篇 20個數字,搜尋加總10000,可成立218個組合
計算次數1048575,程式運行時間約4秒
第二篇 23個數字,搜尋加總7143,可成立180個組合,
計算次數8388607,程式運行時間約30秒(未修正前約80秒)
如果不找全部組合,只找一組,或限定搜尋組數時,剛好小於最大成立組合
或限定每次取出數字個數(3個 or 5個 or ...其它)
基本上,秒解

不過,那種幾百個數字的,還是別用了
我這個 excel vba小品程式,寫的爛

有興趣的拿去玩吧,資料量不多的話,用vba會比規劃求解快很多
程式功能,找出這2個排列組合公式,加總條件成立的組合
2^n-1
c(n,m)=n!/((n-m)!m!)
=========================================================================
'程式用法:
'a1~a??? 放數字(不用排序)
'b1 目標值
'b2 限定每組個數(不填,找所有組合)
'b3 限定最大搜尋組數(不填,找所有組合)
建議先填入一個小一點的數字測試
或自行如入計時功能超過時間就自動結束程式
避免資料太多跑不完

Sub test()
Dim data As Variant, targetsum As Variant, total As Long, i As Long, ok As Long, target As Long, limited As Integer, maxcombin As Integer, start As Integer, startend As Integer
Columns("d:z").Clear'這行視情況,請自行增加清除範圍
data = Application.Transpose(Range("A1", Range("A1").End(xlDown)))
If Range("b1") = 0 Then End
target = Range("b1"): limited = Range("b2"): maxcombin = Range("b3"): Range("b4") = "": Range("b5") = "": Range("d1") = Format(Now(), "hh:mm:ss")
If limited = 0 Then
start = 1: startend = UBound(data)
Else
start = Range("b2"): startend = start
End If
For i = start To startend
ReDim targetsum(1 To i)
Call findCombin(data, targetsum, i, total, 1, 1, ok, target, limited, maxcombin)
If start <> startend Then Range("b5") = Int((i / startend * 100) + 0.5) & "%"
Next i
Range("b5") = "100%": Range("d2") = Format(Now(), "hh:mm:ss"): Debug.Print total
End Sub
Sub findCombin(data As Variant, targetsum As Variant, j As Long, total As Long, k As Long, n As Long, ok As Long, target As Long, limited As Integer, maxcombin As Integer)
Dim i As Long, tempsum As Long
'(20180813更新,注意,如果數值有小數點,請把上面這行改成=> Dim i As Long, tempsum,如果目標值只是一般數字改成tempsum As Double 或是 tempsum As single也可以)
For i = k To UBound(data)
targetsum(n) = data(i): tempsum = 0
If n = j Then
total = total + 1
For s = 1 To UBound(targetsum)
tempsum = tempsum + targetsum(s)
Next s
If tempsum = target Then
'如果目標值有範圍限制
'例如:10<目標值<88
'整個程式只需修改上面那1行if判斷句即可
'至於怎麼改,請自行練習
ok = ok + 1: Range("e" & ok).Resize(1, j) = targetsum
If (ok = maxcombin And maxcombin <> 0) Then
Range("b4") = ok: Range("b5") = "100%": Range("d2") = Format(Now(), "hh:mm:ss"): Debug.Print total
End
End If
Range("b4") = ok
End If
Else
Call findCombin(data, targetsum, j, total, i + 1, n + 1, ok, target, limited, maxcombin)
End If
Next i
End Sub
附加壓縮檔: 201612/mobile01-f62b004a35b1e9bce6be0061f7b78b63.zip
如果沒有目標值,只想看所有的不重覆排列組合,目標值保持空白,程式碼修改如下
注意:組合太多,請先把結果放陣列,最後再放到儲存格,不然計算時間會很恐怖

(點下可看大圖)
