一,題目:輸入兩個整數 n 和 m,從數列1,2,3.......n 中隨意取幾個數,使其和等於 m ,要求將其中所有的可能組合列出來。
二,解釋:比如輸入m=4 n=4 則輸出為:4
1+3 而2+2不正確,因為重複輸出數字了
中心思想:1)如果1+2+3+……+n<m 則不存在這個數
2)如果m<n 則應該讓n=m //因為m--->n之間的數都已經大於m了 沒必要再計算了
3)如果m=n 輸出n
4)如果m>n 遞迴迴圈
源碼採用原型:0-1背包問題
參考部落格:http://blog.csdn.net/tianshuai11/article/details/7025464
三,源碼:(類似源碼五)
#include<list>#include<iostream> using namespace std; list<int> list1; void find_factor(int sum, int n) { // 遞迴出口 if(n <= 0 || sum <= 0) return; // 輸出找到的結果 if(sum == n) { // 反轉list list1.reverse(); for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++) cout << *iter << " + "; cout << n << endl; list1.reverse(); } list1.push_front(n); //典型的01背包問題 find_factor(sum-n, n-1); //放n,n-1個數填滿sum-n list1.pop_front(); find_factor(sum, n-1); //不放n,n-1個數填滿sum } int main() { int sum, n; cout << "請輸入你要等於多少的數值sum:" << endl; cin >> sum; cout << "請輸入你要從1.....n數列中取值的n:" << endl; cin >> n; cout << "所有可能的序列,如下:" << endl; find_factor(sum,n); return 0; }
四,源碼(java方法)
/** * 輸入兩個整數 n 和 m,從數列1,2,3.......n 中 隨意取幾個數,使其和等於 m ,要求將其中所有的可能組合列出來.e.g n=6,m=6 1,2,3 2,4 1,5n= * @author wangxm */public class Comp {static void getAllComp(int n,int m){String pre = m+"=";int theMax = (1+n)*n/2;if(theMax<m){System.out.println("不存在該數!");}else{for(int i=1;i<=m/2;i++){//從1開始計數,列印出兩個數的組合,並且兩數不相等if(i != m-i)System.out.println(pre+i+"+"+(m-i));//調用遞迴,繼續求得大於2個數的組合getTheResult(m-i,pre+i,i);}}}//調用遞迴,繼續求得大於2個數的組合,j為組合中已用過的數,所以取大於該數的。static void getTheResult(int m,String pre,int j){for(int i=j+1;i<=m/2;i++){if(i != m-i)System.out.println(pre+"+"+i+"+"+(m-i));getTheResult(m-i,pre+"+"+i,i);}}public static void main(String[] args) {getAllComp(3,6);}}
五,源碼(容易理解)
#include <iostream> using namespace std; int length; void PrintSolution(int *flag) { for (int i=0;i<length;i++) { if (flag[i]==1) { cout<<i+1<<" "; } } cout<<endl; }void BagProblem(int m,int n, int *flag) { if (n<1||m<1) return; if (m<n) n=m; if (n==m) { flag[n-1]=1; PrintSolution(flag); flag[n-1]=0; } flag[n-1]=1; //n先放入背包中BagProblem(m-n,n-1,flag); //剩餘空間為 m-n 可以取的背包為 1->n-1flag[n-1]=0; //n不放入背包中BagProblem(m,n-1,flag); //剩餘空間為 m 可以取的背包為 1->n-1} int main() { int m,n; cout<<"please input m and n:"<<endl; cin>>m>>n; cout<<"the solution is :"<<endl; length=n; int *flag=(int *)malloc(sizeof(int)*n); memset(flag,0,sizeof(int)*n);//注意memset用法及區分sizeof(flag)/sizeof(int)*n BagProblem(m,n,flag); free(flag); return 0; }
【0-1背包公式】opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i])
解釋如下:
opt[i-1][v] 表示第i件物品不裝入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品裝入背包中。
對應之後:n為物品 m為背包容積,這裡相當於求“所有可能的裝滿的裝法”。忽略了價值的計算即沒有真正計算出那種裝法最佳