整數分解為指定元素的加法表示 找零錢

2021-08-02 22:20:20 字數 1198 閱讀 6125

在實際專案中遇到乙個問題。有乙個總數n,和乙個元素集合,求n可以是由元素集合中的什麼元素相加組成。例如:總數49,元素集合,有如下解:

49 = 3 + 3 + 3 + 7 + 11 + 11 + 11

49 = 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 11 + 11

...

這個問題類似於現實生活中的找零錢,在一些網路棋牌遊戲的斷線重連恢復場景上有應用。

對於這個問題本人實現了乙個演算法,在此分享下。

把乙個數分解若干個相加的集合元素,可以看作是對一棵樹的搜尋。

從根結點開始減元素集合中的元素,某個樹節點的總數被減為0,那個樹節點到樹根結點的路徑就是乙個解。

示意圖如下:

由於是對一棵樹的搜尋,可以用dfs也可以用bfs。演算法步驟如下:

樹節點攜帶2個值:

本節點表示的剩餘總數

乙個元素值,記錄本節點由父節點減掉哪個元素生成的。

根結點的值是總數,演算法初始時只有乙個攜帶總數值的根結點,從這個根結點開始展開整棵樹。

每個節點擴充套件子節點的規則是:

當前結點的總值減掉元素列表中的每個元素,

每次總數減去乙個元素列表中的乙個元素就生成乙個子節點。

當乙個節點的總值為0時,找到了乙個解。

因為總數剛好是被元素集合中的元素減為0的,

通過這條樹路徑可以用一路減掉的元素加回到最初的根結點總數。

當乙個節點的總值小於0時,表明這條樹路徑無解。

以上思路,我實現的程式如下(演算法實現70行左右):

有一些解可以認為是重複的,比如

3 + 7 + 13 + 13 + 13

7 + 3 + 13 + 13 + 13

只是3和7調換了個位置。

這是因為這2個解對應的是2條不同的樹路徑。

如果元素集合中有1的話,就一定會有解,並且有相當多個解。

因為1是萬能配,和自身或者其他任何元素相加都可以達到總數。

下面的鏈結是我乙個朋友的實現,c++,

比較簡潔,核心演算法20多行。

可去掉重複的版本

整數分解為若干項之和

將乙個正整數n分解成幾個正整數相加,可以有多種分解方法,例如7 6 1,7 5 2,7 5 1 1,程式設計求出正整數n的所有整數分解式子。輸入格式 每個輸入包含乙個測試用例,即正整數n 0輸出格式 按遞增順序輸出n的所有整數分解式子。遞增順序是指 對於兩個分解序列n 1 和n 2 若存在i使得n ...

整數分解為若干項之和

將乙個正整數n分解成幾個正整數相加,可以有多種分解方法,例如7 6 1,7 5 2,7 5 1 1,程式設計求出正整數n的所有整數分解式子。每個輸入包含乙個測試用例,即正整數n 0 30 按遞增順序輸出n的所有整數分解式子。遞增順序是指 對於兩個分解序列n 1 和n 2 若存在i使得n 1 m 1 ...

整數分解為2的冪 數學

任何正整數都能分解成2的冪,給定整數n,求n的此類劃分方法的數量!由於方案數量較大,輸出mod 1000000007的結果。比如n 7時,共有6種劃分方法。7 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 2 1 2 2 2 1 1 1 4 1 2 4 input輸入乙個數n ...