從數列1,2,3,......,n中隨意取出幾個數,使其和等於m
阿新 • • 發佈:2019-01-25
問題描述:
輸入兩個整數n和m,從數列1,2,3,.......n中隨意去幾個數,使其和等於m,要求將其中所有可能的組合列出來。
解決思路:
這個問題其實是揹包問題的變形,給出兩種解決方法。
解法一:
用遞迴,效率可能低了點。假設問題的解為F(n,m),可分為兩個子問題F(n-1,m-n)和F(n-1,m)。對於這兩個問題遞迴求解,求解的過程中,如果找到了符合條件的數字組合,則打印出來。
解法二:
用迴圈,其實就是列舉所有組合。對於n,組合數應該為2^n。我們可以用一個數字i來表示組合。如果i = 5,其二進位制形式為101,相應的組合為{1,3}。也就是說,二進位制的每一位都表示一個數字,bit0代表數字1,bit1代表數字2,依次類推。當某位為1,表示選中了該位所表示的數字。
參考程式碼
輸入兩個整數n和m,從數列1,2,3,.......n中隨意去幾個數,使其和等於m,要求將其中所有可能的組合列出來。
解決思路:
這個問題其實是揹包問題的變形,給出兩種解決方法。
解法一:
用遞迴,效率可能低了點。假設問題的解為F(n,m),可分為兩個子問題F(n-1,m-n)和F(n-1,m)。對於這兩個問題遞迴求解,求解的過程中,如果找到了符合條件的數字組合,則打印出來。
解法二:
用迴圈,其實就是列舉所有組合。對於n,組合數應該為2^n。我們可以用一個數字i來表示組合。如果i = 5,其二進位制形式為101,相應的組合為{1,3}。也就是說,二進位制的每一位都表示一個數字,bit0代表數字1,bit1代表數字2,依次類推。當某位為1,表示選中了該位所表示的數字。
參考程式碼
-
#include <iostream>
-
using namespace std;
-
//函式功能:從數列1,2,3......n中隨意取幾個數,使其和等於m
-
//函式引數:n為當前最大值,m為剩餘值,flag標記選中與否,len為flag的容量
-
//返回值: 無
-
void BagProlem_Solution1(int n, int m, int *flag, int len)
-
{
-
if(n < 1 || m < 1)
-
{
-
return;
-
}
-
if(n < m)
-
{
-
flag[n - 1] =
-
BagProlem_Solution1(n - 1, m - n, flag, len); //選了n
-
flag[n - 1] = 0;
-
BagProlem_Solution1(n - 1, m, flag, len); //不選n
-
}
-
else
-
{
-
flag[m - 1] = 1; //n >= m,選中m即可(n = m)
-
for(int i = 0; i < len; i++)
-
{
-
if(flag[i] == 1)
-
{
-
cout << i + 1 << "
";
-
}
-
}
-
cout << endl;
-
flag[m - 1] = 0; //不選m,繼續遞迴。比如n = 10, m = 8,求出{1,7}後,仍需繼續,{1,3,4}和{1,2,5}都是解
-
BagProlem_Solution1(m - 1, m, flag, len);
-
}
-
}
-
//函式功能:從數列1,2,...n中隨意選取幾個數,使其和等於m
-
//函式引數:n為當前最大值,m為剩餘值
-
//返回值: 無
-
void BagProlem_Solution2(int n, int m)
-
{
-
if(n < 1 || m < 1)
-
{
-
return;
-
}
-
if(n > m)
-
{
-
n = m;
-
}
-
int num = 1 << n; //列舉次數
-
for(int i = 1; i < num; i++)
-
{
-
int sum = 0;
-
int j, k;
-
for(j = i, k = 1; j != 0; j >>= 1, k++)
-
{
-
if(j & 1)
-
{
-
sum += k;
-
}
-
}
-
if(sum == m)//如果滿足,列印結果
-
{
-
for(j = i, k = 1; j != 0; j >>= 1, k++)
-
{
-
if(j & 1)
-
{
-
cout << k << "
";
-
}
-
}
-
cout << endl;
-
}
-
}
-
}
-
int main()
-
{
-
int n, m;
-
cout<<"please enter n and m : ";
-
cin>>n>>m;
-
int *flag = new int[n];
-
for(int i = 0; i < n; i++)
-
{
-
flag[i] = 0;
-
}
-
BagProlem_Solution1(n, m, flag, n);
-
cout<<endl;
-
BagProlem_Solution2(n, m);
-
delete [] flag;
-
return 0;
- }