1. 程式人生 > >演算法-1到n中所有和為m的組合

演算法-1到n中所有和為m的組合

題目:
輸入兩個整數 n 和 m,從數列1,2,3…….n 中隨意取幾個數,使其和等於 m ,要求將其中所有的可能組合列出來。

解題思路:
好未來筆試題中的一道題目,是揹包問題的一個衍生問題,設i是1,2,3…….n 中的一個數,那麼從i=1開始,(n,m,i)的問題就可以變成(n,m-i,i+1)的子問題,依次遞迴下去,這樣會有兩個結果,一個是m被減成了0,一個是i比m大甚至i比n大。出現前者時,滿足條件的一組結果就找到了,而後者做為某一層遞迴退出的條件。舉個例子,假設n=3,m=4,i的初始值為1,組合結果為v:
呼叫函式:(3,4,1) v[1]
第一層遞迴:(3,3,2) v[1,2]
第二層遞迴:(3,1,3) i>m 退回到第一層
第一層遞迴:(3,3,3) v[1,3]
第二層遞迴:(3,0,4) m=0 找到滿足條件的一組數 退回到第一層,且i>m 退回到第一層
第一層遞迴:(3,3,4) v[1,4] i>m 退回到第0層
呼叫函式:(3,4,2) v[2]
.
.
.
直到在第0層的時候,i>n,即 v[3]的情況,所有的遞迴就都結束了。

程式碼實現:

#include "iostream"    
#include<vector>
using namespace std;
void Combination(int n, int m, vector<int>& v, int beg) 
{
    if (m == 0) 
    {
        for (int i = 0; i<v.size(); i++)
        {
            i == 0 ? cout << v[i] : cout << " " << v[i];
        }
        cout
<< endl; } for (int i = beg; i <= n&&i <= m; i++) { v.push_back(i); Combination(n, m - i, v, i + 1); v.pop_back(); } } int main() { int n, m; while (cin >> n >> m) { if (n<1) return 0; vector
<int>
v; Combination(n, m, v, 1); } }